<!DOCTYPE html>
<html lang="en">
	<head>
		<title>nTube</title>
		<meta name="application-name" content="nTube" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<meta name="iwebkit-use-fruit-styled-layout" value="true;version=1" />
		<meta name="apple-mobile-web-app-capable" content="yes" />
		<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
		<meta name="description" content="nTube: Video page, a video would be here." />
		<meta name="robots" content="noindex, nofollow" />
		<meta charset="UTF-8" />
		<meta name="theme-color" content="#282828" />
		<link rel="manifest" href="/manifest.json" />
		<link rel="apple-touch-icon" href="/resources/logos/ntube-logo-192.png" />
		<link rel="preload" href="resources/libWeb.js" as="script" />
		<link rel="preload" href="resources/promise-queues.js" as="script" />
		<link rel="preload" href="resources/base.js" as="script" />
		<link rel="preload" href="resources/base_es6_funcs.js" as="script" />
		<link rel="preload" href="resources/nPlayerNX.js" as="script" />
		<link rel="preload" href="resources/settings.js" as="script" />
		<link rel="preload" href="resources/filters.js" as="script" />
		<link rel="preload" href="resources/dash.js" as="script" />
		<link rel="preload" href="resources/search.js" as="script" />
		<link rel="preload" href="resources/ntube_next/nTubeNextAPI.js" as="script" />
		<link rel="preload" href="resources/commander.js" as="script" />
		<link rel="preload" href="resources/redwood/redwood_drm.js" as="script" />
		<script src="resources/libWeb.js"></script>
		<script src="resources/promise-queues.js"></script>
		<script src="resources/base.js"></script>
		<script src="resources/base_es6_funcs.js"></script>
		<script src="resources/nPlayerNX.js" defer="defer"></script>
		<script src="resources/settings.js" defer="defer"></script>
		<script src="resources/filters.js" defer="defer"></script>
		<script src="resources/search.js" async="async"></script>
		<script src="resources/ntube_next/nTubeNextAPI.js" defer="defer"></script>
		<script src="resources/commander.js"></script>
		<script src="resources/redwood/redwood_drm.js" defer="defer"></script>
		<script src="resources/superxbr.js" defer="defer"></script>
		<!-- -->
		<script src="fun/2024af.js" defer="defer"></script>
		<!-- -->
		<link rel="stylesheet" type="text/css" href="resources/base.css" />
		<link rel="stylesheet" type="text/css" href="resources/search.css" />
		<link rel="stylesheet" type="text/css" href="resources/commander.css" />
		<link rel="search" type="application/opensearchdescription+xml" title="Search not(You)Tube." href="/nsearch.xml" />
		<style id="poly-item-css">
			.poly-item {
				padding-left: 5px;
				box-shadow: 0 14px 28px rgba(255, 255, 255, 0.11), 0 10px 10px rgba(255, 255, 255, 0.08);
				border: 1px solid white;
				margin-bottom: 10px;
			}
		</style>
		<style id="collapsible-css">
			.active,
			.collapsible:hover {
				background-color: #555;
			}
		</style>
		<style id="body-css">
			body {
				background-color: black;
				color: white;
			}
		</style>
		<!--rgba(80, 80, 80, 0.3)-->
		<style>
			* {
				-webkit-font-smoothing: antialiased;
				-moz-osx-font-smoothing: grayscale;
			}

			.menu {
				position: fixed;
				top: 0;
				margin: auto;
				left: 0;
				right: 0;
				width: 100%;
				height: 32px;
				border-bottom: 1px solid green;
				margin-right: 0px;
				z-index: 15;
				display: -webkit-box;
				display: -moz-box;
				display: -ms-flexbox;
				display: -webkit-flex;
				display: flex;
			}

			.menu-item {
				-webkit-box-flex: 1;
				-moz-box-flex: 1;
				-webkit-flex: 1;
				-ms-flex: 1;
				flex: 1;
				max-width: 50%;
				overflow: hidden;
				white-space: nowrap;
			}

			.poly-item-light {
				padding-left: 5px;
				box-shadow: 0 14px 28px rgba(0, 0, 0, 0.15), 0 10px 10px rgba(0, 0, 0, 0.12);
				border: 1px solid black;
				margin-bottom: 10px;
			}

			.yt-uix-sessionlink {
				color: inherit;
			}

			.collapsible {
				background: inherit;
				border: none;
				border-bottom: 2px solid green;
				color: inherit;
				cursor: pointer;
				padding: 12px;
				margin-left: -5px;
				width: calc(100% + 5px);
				text-align: left;
				outline: none;
				font-size: 15px;
				font-family: inherit;
			}

			.content {
				padding: 0 18px;
				max-height: 0;
				overflow: hidden;
				transition: max-height 0.2s ease-in-out;
				background-color: inherit;
			}

			.show {
				display: block;
			}

			.not-a-overlay {
				z-index: 4;
				position: fixed;
				background-color: rgba(0, 0, 0, 0.8);
			}

			.fix-360-viewer {
				position: relative !important;
			}

			#__360_alt_canvas_div > canvas {
				margin: 0 !important;
			}

			video:focus {
				outline: none;
			}

			@-moz-document url-prefix() {
				.view360-canvas {
					position: relative !important;
				}
			}

			.flat-button {
				border: 1px solid rgba(0, 255, 40, 0.5);
				padding: 5px;
				background-color: rgba(0, 0, 0, 0.5);
				backdrop-filter: blur(5px);
			}

			.flat-button:disabled {
				filter: grayscale(1);
			}

			.ntube-livestream-chat-div {
				--dummy: 1;
			}

			@media only screen and (max-device-width: 768px) {
				#_primary_player {
					width: 100% !important;
					height: auto !important;
				}

				.ntube-livestream-chat-div {
					float: unset !important;
					clear: left !important;
					width: 100% !important;
					height: 50vh !important;
				}
			}
		</style>
		<style id="_css_fonts">
			html {
				font-family: -apple-system, BlinkMacSystemFont, "Product Sans", "Google Sans", "Segoe UI", "Arial", sans-serif;
			}
		</style>
		<style id="_subtitle_css">
			::cue,
			video::cue,
			div[pseudo="cue"] {
				padding: 5px;
				border: 1px solid green;
				font-family: inherit;
			}
		</style>
		<script async="async">
			function isChromeFunc() {
				try {
					return (typeof window.chrome === "object" || typeof window.chrome.runtime === "object" || typeof window.chrome.csi === "function") && typeof InstallTrigger !== "object";
				} catch (e) {
					return false;
				}
			}
			var isChrome = false;
			try {
				isChrome = (typeof window.chrome === "object" || typeof window.chrome.runtime === "object" || typeof window.chrome.csi === "function") && typeof InstallTrigger !== "object";
			} catch (e) {}
			window.yt = {
				www: {
					watch: {
						player: {
							seekTo: function (time) {
								console.log("nTube: Seeking to " + time + ".");
								if (window.mainPlayer) {
									window.mainPlayer.seek(time);
								} else {
									var pp = document.getElementById("_primary_player"); // FIXME: Don't cache since we break until we exit the cache.
									if (pp == null) {
										try {
											pp = document.getElementsByClassName("video-stream html5-main-video")[0];
										} catch (e) {}
									}
									if (pp.tagName === "DIV") {
										pp = pp.children[0];
									}
									pp.currentTime = time;
								}
							},
						},
					},
				},
			};
			window.__init = function () {
				try {
					nTube.init();
					nTube.initTheming();
				} catch (e) {
					console.error(e);
				}
				if (window.location.toString().contains("file:///")) {
					console.warn("nTube was opened locally, not extracting.");
					return;
				}
				const VIDEO_ID = getQueryVariable("v");
				if (VIDEO_ID == null || VIDEO_ID.length == 0) {
					alert("nTube encountered an error.\r\nError: VIDEO_ID is null or blank!");
					return;
				}
				id("__debug_overlay_video_id").innerHTML = VIDEO_ID;
				var ENABLE_360_SUPPORT = supportsWebGL() && !getQueryVariable("no360");
				var LOCAL_PREFER = getQueryVariable("prefer");
				var GLOBAL_PREFER = -1;
				var av1Action = "def";
				var allowWebM = false;
				var remove30FPSVideos = false;
				var remove60FPSVideos = false;
				var DASH_JS_ENABLE_QUALITY_ENFORCEMENT = false;
				var USE_10_BIT_CONTENT = false;
				var BLOCK_SPONSORS = false;
				var PLAYBACK_ENGINE = "rxplayer";
				var EMULATE_MSE_MISSING = getQueryVariable("emu_no_mse") !== null;
				var PLAYBACK_BEHAVIOUR = "auto";
				var ENABLE_EQUALIZER = false;
				var ENABLE_CASTING = false;
				var ENABLE_DRM_SUPPORT = false;
				var ENABLE_NEW_WEB_FEATURES = false;
				var ENABLE_CACHE = false;
				var REDUCE_QUALITY_FOR_LOAD = false;
				var REDUCE_QUALITY_FOR_AV1 = false;
				var ENABLE_LOW_LATENCY_HLS = false;
				var ENABLE_DISLIKE_FETCHING = false;
				var ENABLE_AUDIO_ONLY_MODE = getQueryVariable("audio") !== null;
				var DISABLE_LOCALIZED_VIDEO_TEXT = false;
				var ENABLE_LAZY_VP = false;
				var UPDATE_METADATA_OVER_TIME = false;
				var ENABLE_PRIVACY_MODE = false;
				var ENABLE_DATA_SAVER = false;
				/* Phones and other low power sound chips support offloading AAC decoding to it's hardware. */
				var PREFER_AAC_OVER_OPUS = isMobile || libWeb.BrowserEnvironment.isChromeOS;
				/* IE11 doesn't support Opus, force AAC instead. Also use values from PREFER_AAC_OVER_OPUS. */
				var NPLAYER_FORCE_AAC = isMobile || libWeb.BrowserEnvironment.isChromeOS || libWeb.BrowserEnvironment.isIE11;
				var USE_RANDOM_VIDEO_CDN = false;
				var ENABLE_TOTAL_ADVERTISER_DEATH = false;
				var ENABLE_IOS_HLS = false;
				if (readSettingsToJSON() !== null) {
					console.warn("You have the legacy nTube settings API stored, this is deprecated and support will be removed in nTube 1.6.");
					const SETTINGS = readSettingsToJSON();
					if (SETTINGS.preferQuality) {
						GLOBAL_PREFER = SETTINGS.preferQuality;
					}
					if (SETTINGS.useWebM) {
						allowWebM = SETTINGS.useWebM && supportsVideoType("vp9") === "probably";
					}
					if (SETTINGS.useDataSaving) {
						ENABLE_DATA_SAVER = SETTINGS.useDataSaving;
					}
				} else {
					const Config = nTubeSettings.auto();
					window.Config = Config;
					if (Config.extraction.defaultQuality) {
						GLOBAL_PREFER = Config.extraction.defaultQuality;
					}
					if (Config.extraction.reduceQuality) {
						REDUCE_QUALITY_FOR_LOAD = Config.extraction.reduceQuality;
					}
					if (Config.extraction.lowQualityAV1Only) {
						REDUCE_QUALITY_FOR_AV1 = Config.extraction.lowQualityAV1Only;
					}
					if (Config.extraction.allowWebM) {
						allowWebM = Config.extraction.allowWebM && supportsVideoType("vp9") === "probably";
					}
					if (Config.appearance.enable_new_look) {
						id("poly-item-css").innerHTML =
							".poly-item {padding-left: 5px; box-shadow: 0 14px 28px rgba(255, 255, 255, 0.08), 0 10px 10px rgba(255, 255, 255, 0.08); border: 1px solid rgba(255, 255, 255, 0.2); margin-bottom: 10px;}";
						id("collapsible-css").innerHTML = ".active, .collapsible:hover {background-color: rgba(80, 80, 80, 0.3);}";
					}
					if (Config.appearance.use_newer_ui_preset) {
						try {
							id("body-css").innerHTML = "body {background-color: #111111; color: white;}";
						} catch (e) {
							console.error(e);
						}
					}
					if (Config.appearance.subtitles) {
						var x = Config.appearance.subtitles;
						const sub = nTube.nTubeUtils.subtitleFor(x);
						if (sub !== null) {
							id("_subtitle_css").innerHTML = sub;
						}
					}
					if (Config.playback.dash_js_remove_30) {
						remove30FPSVideos = Config.playback.dash_js_remove_30;
					}
					if (Config.playback.dash_js_force_quality_init) {
						DASH_JS_ENABLE_QUALITY_ENFORCEMENT = Config.playback.dash_js_force_quality_init;
					}
					if (Config.extraction.av1_behaviour) {
						av1Action = Config.extraction.av1_behaviour;
					}
					if (Config.appearance.custom_css) {
						try {
							id("ntube-custom-css").innerHTML = base64Decode(Config.appearance.custom_css);
						} catch (e) {
							console.error(e);
						}
					}
					if (Config.extraction.enable10bit) {
						USE_10_BIT_CONTENT = Config.extraction.enable10bit;
					}
					if (Config.extraction.dataSaving) {
						if (Config.extraction.dataSaving === "on") {
							ENABLE_DATA_SAVER = true;
						} else if (Config.extraction.dataSaving === "auto") {
							ENABLE_DATA_SAVER = isDataSaver();
						}
					}
					if (Config.global.sponsor_blocking) {
						BLOCK_SPONSORS = Config.global.sponsor_blocking;
					}
					if (Config.playback.playback_engine) {
						PLAYBACK_ENGINE = Config.playback.playback_engine;
					}
					if (Config.global.enable_clv) {
						ENABLE_EQUALIZER = Config.global.enable_clv;
					}
					if (Config.global.experiments && Config.global.experiments.chromecast) {
						ENABLE_CASTING = Config.global.experiments.chromecast;
					}
					if (Config.global.experiments && Config.global.experiments.allow_drm) {
						ENABLE_DRM_SUPPORT = Config.global.experiments.allow_drm;
					}
					if (Config.global.experiments && Config.global.experiments.new_web_features) {
						ENABLE_NEW_WEB_FEATURES = Config.global.experiments.new_web_features;
					}
					if (Config.global.experiments && Config.global.experiments.hls_force_ll) {
						ENABLE_LOW_LATENCY_HLS = Config.global.experiments.hls_force_ll;
					}
					if (Config.global.enable_video_cache) {
						ENABLE_CACHE = Config.global.enable_video_cache;
					}
					if (Config.global.experiments && Config.global.experiments.return_dislikes) {
						ENABLE_DISLIKE_FETCHING = Config.global.experiments.return_dislikes;
					}
					if (Config.global.experiments && Config.global.experiments.out_of_order_extraction) {
						ENABLE_LAZY_VP = Config.global.experiments.out_of_order_extraction;
					}
					if (Config.global.experiments && Config.global.experiments.update_metadata_ls) {
						UPDATE_METADATA_OVER_TIME = Config.global.experiments.update_metadata_ls;
					}
					if (Config.global.experiments && Config.global.experiments.random_video_cdn) {
						USE_RANDOM_VIDEO_CDN = Config.global.experiments.random_video_cdn;
					}
					if (Config.global.experiments && Config.global.experiments.use_ios_hls) {
						ENABLE_IOS_HLS = Config.global.experiments.use_ios_hls;
					}
					if (Config.global.disable_localized_video_text) {
						DISABLE_LOCALIZED_VIDEO_TEXT = Config.global.disable_localized_video_text;
					}
					if (Config.global.advertiser_death) {
						ENABLE_TOTAL_ADVERTISER_DEATH = Config.global.advertiser_death;
					}
				}
				function getUTCOffset() {
					if (window.Date && window.Date.prototype.getTimezoneOffset) {
						return new Date().getTimezoneOffset();
					} else {
						return 120;
					}
				}
				function allowAV1() {
					if (av1Action === "def") {
						if (isBattery()) return false;
						return supportsAV1playback() || getQueryVariable("av1") !== null;
					} else {
						return av1Action === "fon";
					}
				}
				const ENABLE_MPD_DASH = nTube.nTubeUtils.isPlaybackEngineDASH(PLAYBACK_ENGINE);
				const jxr = {
					next_api_version: 2,
					videoID: VIDEO_ID,
					enableAV1: allowAV1(),
					enableWebM: allowWebM || getQueryVariable("allowWebM") !== null,
					isBitChute: getQueryVariable("bc") !== null,
					dataSaver: ENABLE_DATA_SAVER || getQueryVariable("dataSaving") !== null,
					enableDashJS: ENABLE_MPD_DASH,
					dashJSUseCompression: false,
					dashJSAllowCaching: true,
					preferredQuality: -1,
					dashJS_force60FPS: remove30FPSVideos || getQueryVariable("mpdForce60") !== null,
					dashJS_force30FPS: (remove60FPSVideos && !remove30FPSVideos) || (getQueryVariable("mpdForce30") !== null && getQueryVariable("mpdForce60") === null),
					enableHDR: USE_10_BIT_CONTENT || getQueryVariable("enableHDR") !== null,
					clar: getQueryVariable("clar") !== null,
					reduceLoad: REDUCE_QUALITY_FOR_LOAD,
					av1_only_lowRes: REDUCE_QUALITY_FOR_AV1,
					audioOnly: ENABLE_AUDIO_ONLY_MODE,
					lazy_vp: PLAYBACK_ENGINE !== "nMuxer" && PLAYBACK_ENGINE !== "nPlayerNX" && ENABLE_LAZY_VP,
					privacyMode: ENABLE_PRIVACY_MODE,
					disable_webvtt_styling: libWeb.BrowserEnvironment.isFirefox,
					nplayer_force_aac: NPLAYER_FORCE_AAC,
					random_video_cdn: USE_RANDOM_VIDEO_CDN,
					fad_tad: ENABLE_TOTAL_ADVERTISER_DEATH,
					use_ios_hls: ENABLE_IOS_HLS,
					systemInfo: {
						utcTimezoneOffset: getUTCOffset(),
					},
					telemetry: {
						h264: supportsVideoType("h264") === "probably",
						vp9: supportsVideoType("vp9") === "probably",
						av1: supportsAV1playback(),
						client: libWeb.BrowserEnvironment.getBrowserVersion(),
						frontend: "ntube-ui",
					},
				};
				var url = "/api/get_video";
				if (LOCAL_PREFER != null) {
					jxr["preferredQuality"] = LOCAL_PREFER;
				} else if (GLOBAL_PREFER != -1) {
					jxr["preferredQuality"] = GLOBAL_PREFER;
				}
				if (getQueryVariable("av_date")) {
					jxr["av_date"] = getQueryVariable("av_date");
				}
				if (getQueryVariable("list") !== null) {
					url += "&list=" + getQueryVariable("list");
				}
				if (getQueryVariable("index") !== null) {
					url += "&index=" + getQueryVariable("index");
				}
				if (window.Config && window.Config.appearance.enable_apple_look) {
					id("_primary_player").poster = "https://i.ytimg.com/vi/" + VIDEO_ID + "/maxresdefault.jpg";
					id("fruit_loader").style.display = "";
					id("fruit_loader").style.visibility = "";
				}
				if (ENABLE_CACHE) {
					window.nTube.cache = new Cache(8, false, new Cache.SessionStorageCacheStorage("ntube-cache"));
					console.debug("Cache loaded, active entries: " + nTube.cache.size());
				}
				function fetchDislikes() {
					request(
						"/api/experimental/get_dislikes?v=" + VIDEO_ID,
						null,
						function (error) {
							console.error("Failed to get dislike data!");
							console.error(error);
						},
						function (dat) {
							const obj = JSON.parse(dat);
							if (obj["dislikes"] && obj["likes"]) {
								id("video_rating_pre").title = numberWithCommas(obj["likes"]) + " likes / " + numberWithCommas(obj["dislikes"]) + " dislikes";
								console.debug("[experiments] Re-added dislike info.");
							}
							if (obj["rating"]) {
								id("video_rating_g").innerHTML = "";
								const rating_percentage = (obj["rating"] / 5) * 100;
								id("video_rating_g").style.width = rating_percentage + "%";
							}
						}
					);
				}
				function preCacheID(videoID) {
					if (ENABLE_CACHE && window.nTube && window.nTube.cache) {
						const jxr_cloned = jxr;
						jxr_cloned["videoID"] = videoID;
						request(
							url.replace("?v=" + VIDEO_ID, "?v=" + videoID),
							JSON.stringify(jxr_cloned),
							function (error) {
								console.error("Failed to pre-cache video!", error);
							},
							function (data) {
								/* TODO(MAINLINE): We should check for errors and disregard cache candidates if that happens. */
								window.nTube.cache.setItem(videoID, data, {
									expirationAbsolute: null,
									expirationSliding: 180,
									priority: Cache.Priority.NORMAL,
								});
							}
						);
						displayMessage("nTube: Playlist.", "Pre-caching next video...", 5000);
					}
				}
				function __init_hls_js(mainPlayer, videoURL, useLL) {
					loadScripts(["/resources/hls.js"], function () {
						if (supportsHLSWorkedAround(mainPlayer)) {
							console.info("Handling livestream, hold on... (method=hls_native)");
							mainPlayer.src = videoURL;
							mainPlayer.controls = true;
						} else if (Hls.isSupported()) {
							console.info("Handling livestream, hold on... (method=hls)");
							var hlsConfig = {
								defaultAudioCodec: "mp4a.40.2",
								fragLoadingTimeOut: 80000,
								maxBufferLength: isMobile || is_iPhoneOS() ? 30 : navigator.userAgent.contains("CrKey") ? 45 : 120,
								enableWorker: true,
							};
							if (ENABLE_LOW_LATENCY_HLS || useLL) {
								if (useLL) {
									console.warn("Stream is flagged as low-latency, enabling low-latency HLS.");
								} else {
									console.warn("You have enabled low-latency HLS, this might break things.");
								}
								hlsConfig = window.mergeJSON(hlsConfig, {
									maxBufferLength: 25,
									liveBackBufferLength: 0,
									liveSyncDuration: 0,
									liveMaxLatencyDuration: 15,
									liveDurationInfinity: true,
									lowLatencyMode: true,
								});
							}
							var hls = new Hls(hlsConfig);
							window.globalHLS = hls;
							hls.loadSource(videoURL);
							hls.attachMedia(mainPlayer);
							hls.on(Hls.Events.MANIFEST_PARSED, function () {
								mainPlayer.play();
								mainPlayer.controls = true;
							});
						} else {
							console.info("Handling livestream, hold on... (method=fallback)");
							alert("nTube: Failed to handle livestream.\nhls.js isn't supported by your browser.");
							mainPlayer.src = videoURL;
							mainPlayer.controls = true;
						}
					});
					const proxied = window.XMLHttpRequest.prototype.open;
					window.XMLHttpRequest.prototype.open = function () {
						if (arguments.length >= 2) {
							const rURL = arguments[1];
							if (rURL.contains("https://manifest.googlevideo.com/api/manifest/") && rURL.contains("/captions/")) {
								arguments[1] = "/proxyAPI?url=" + base64Encode(rURL) + "&treatAsB64";
							}
						}
						return proxied.apply(this, [].slice.call(arguments));
					};
					window.nTubeVideo = { syncMethod: "hls" };
				}
				function loadComments(n, _commentDiv, _commentButton) {
					if (n === null || n === undefined || n.length === 0) return;
					const commentButton = _commentButton == null ? id("_comments_initial_button") : _commentButton;
					commentButton.disabled = true;
					request(
						"/api/get_comments",
						JSON.stringify(n),
						function (error) {
							console.error(error);
							alert("Failed to load comments.\nCheck your browser console for more information.");
							hide(id("_comments_initial_div"));
						},
						function (data) {
							const m = JSON.parse(data);
							if (m["error"]) {
								console.error(m);
								if (m["error"]["reason"] === "NCAPTCHA_SOLUTION_REQUIRED") {
									alert("nCaptcha: Captcha required!\nYour session token has expired and you will need to reload and do a challenge to continue.\nSorry about that. :/");
									commentButton.disabled = false;
								} else {
									alert("Failed to load comments.\nCheck your browser console for more information.");
									hide(id("_comments_initial_div"));
								}
							} else {
								if (m["cont"]) {
									const newObj = Object.assign({}, n);
									newObj["token"] = m["cont"];
									commentButton.onclick = function () {
										loadComments(newObj, _commentDiv);
									};
									commentButton.innerHTML = "Load more comments.";
									commentButton.disabled = false;
								} else {
									commentButton.disabled = true;
									commentButton.innerHTML = "No more comments.";
								}
								const comments = m["comments"];
								const cmntdiv = _commentDiv == null ? id("_comments") : _commentDiv;
								if (_commentDiv == null) {
									try {
										const cnt = parseInt(id("_comments_count").innerHTML);
										id("_comments_count").innerHTML = comments.length + cnt;
									} catch (e) {
										console.error(e);
										id("_comments_count").innerHTML = comments.length + "";
									}
								}
								for (var i = 0; i < comments.length; i++) {
									const comment = comments[i];
									const commentDiv = document.createElement("div");
									commentDiv.style.backgroundColor = "rgba(34, 34, 34, 0.5)";
									commentDiv.style.display = "grid";
									commentDiv.style.width = "calc(100vw - 30px)";
									const _topInfoDiv = document.createElement("div");
									const _topInfoImg = document.createElement("img");
									_topInfoImg.src = comment["authorURL"];
									_topInfoImg.style.width = "48px";
									_topInfoImg.style.height = "48px";
									_topInfoImg.style.verticalAlign = "middle";
									_topInfoImg.style.paddingLeft = "3px";
									_topInfoImg.loading = "lazy";
									_topInfoImg.decoding = "async";
									_topInfoImg.referrerPolicy = "no-referrer";
									const _topInfoText = document.createElement("p");
									_topInfoText.style.verticalAlign = "middle";
									_topInfoText.style.display = "inline";
									_topInfoText.style.marginLeft = "5px";
									const _authorNameSpan = document.createElement("span");
									_authorNameSpan.innerHTML = comment["author"];
									if (comment["author_verified"] && comment["author_verified"] === true) {
										_authorNameSpan.innerHTML += '<b class="user-verified" title="This user is verified.">&check;</b>';
									}
									_topInfoText.appendChild(_authorNameSpan);
									if (comment["likes"]) {
										_topInfoText.innerHTML += "&nbsp;&centerdot;&nbsp;";
										var d = document.createElement("span");
										d.style.fontFamily = "monospace";
										if (comment["likes"] === 1) {
											d.innerHTML = comment["likes"] + " like.";
										} else {
											d.innerHTML = comment["likes"] + " likes.";
										}
										_topInfoText.appendChild(d);
									}
									if (comment["authorLike"] === true) {
										_topInfoText.innerHTML += "&nbsp;&centerdot;&nbsp;";
										var d = document.createElement("span");
										d.title = "Liked by author.";
										d.innerHTML = "&#128077;";
										_topInfoText.appendChild(d);
									}
									if (comment["isHearted"] === true) {
										_topInfoText.innerHTML += "&nbsp;&centerdot;&nbsp;";
										var d = document.createElement("span");
										d.title = "Hearted by author.";
										d.innerHTML = "&#9829;";
										_topInfoText.appendChild(d);
									}
									if (comment["pinnedByAuthor"] === true) {
										_topInfoText.innerHTML += "&nbsp;&centerdot;&nbsp;";
										var d = document.createElement("span");
										d.title = "Pinned by author.";
										d.innerHTML = "&#128204;";
										_topInfoText.appendChild(d);
									}
									_topInfoDiv.appendChild(_topInfoImg);
									_topInfoDiv.appendChild(_topInfoText);
									const commentSplit = document.createElement("hr");
									commentSplit.classList.add("flex_hr_compat");
									commentDiv.appendChild(_topInfoDiv);
									commentDiv.appendChild(commentSplit);
									const commentText = document.createElement("div");
									commentText.innerText = comment["comment"];
									commentText.style.marginLeft = "15px";
									commentText.style.marginRight = "15px";
									commentText.style.marginTop = "5px";
									commentText.style.marginBottom = "5px";
									commentDiv.appendChild(commentText);
									const cmntReplyDiv = document.createElement("div");
									cmntReplyDiv.style.marginBottom = "15px";
									cmntReplyDiv.style.marginTop = "3px";
									cmntReplyDiv.style.marginLeft = "15px";
									cmntReplyDiv.style.marginRight = "15px";
									cmntReplyDiv.classList.add("flex_box_compat", "flex_wrap_compat");
									hide(cmntReplyDiv);
									commentDiv.appendChild(cmntReplyDiv);
									if (comment["replies"]) {
										const _next_token = comment["replies"];
										commentDiv.setAttribute("next-token", _next_token);
										const commentRepliesLoader = document.createElement("button");
										commentRepliesLoader.classList.add("flat-button");
										commentRepliesLoader.style.color = "inherit";
										commentRepliesLoader.style.fontFamily = "inherit";
										commentRepliesLoader.style.fontSize = "medium";
										commentRepliesLoader.style.border = "1px solid green";
										commentRepliesLoader.style.marginBottom = "15px";
										commentRepliesLoader.style.marginTop = "3px";
										commentRepliesLoader.style.marginLeft = "10px";
										commentRepliesLoader.style.marginRight = "10px";
										if (comment["replyCount"]) {
											commentRepliesLoader.innerHTML = "Load " + comment["replyCount"] + " more replies.";
										} else {
											commentRepliesLoader.innerHTML = "Load more.";
										}
										commentRepliesLoader.onclick = function () {
											show(cmntReplyDiv);
											const __new_payload = cloneJSON(jsonObject.metadata.comments);
											__new_payload["token"] = _next_token;
											loadComments(__new_payload, cmntReplyDiv, commentRepliesLoader);
										};
										commentDiv.appendChild(commentRepliesLoader);
									}
									cmntdiv.appendChild(commentDiv);
								}
							}
						}
					);
				}
				window.__loadComments = loadComments;
				function process_endscreen(jsonObject) {
					try {
						if (jsonObject.metadata && jsonObject.metadata["endscreen"] && jsonObject.metadata["endscreen"].length > 0) {
							const eo = id("endscreen_div");
							id("__endscreen").style.display = "";
							id("__endscreen").style.visibility = "";
							for (var i = 0; i < jsonObject.metadata["endscreen"].length; i++) {
								const data = jsonObject.metadata["endscreen"][i];
								var videoDiv = document.createElement("div");
								videoDiv.classList.add("endscreen-video");
								videoDiv.classList.add("poly-item");
								videoDiv.classList.add("endscreen-video-poly");
								videoDiv.style.marginBottom = "5px";
								const a = document.createElement("a");
								a.classList.add("endscreen-link-main");
								if (data["type"] === "website" && ENABLE_NEW_WEB_FEATURES && nTubeNext.Platform.is("vendor=chrome;version>=85;feature=portals") && window.addPreviewPortal) {
									const _url = data["url"] + "&portals_timeout_longer";
									a.onclick = function () {
										addPreviewPortal(_url);
									};
								} else {
									a.href = data["url"];
								}
								const image = document.createElement("img");
								image.style.verticalAlign = "middle";
								image.style.display = "table-row";
								image.style.maxWidth = "160px";
								image.style.height = "90px";
								image.style.width = "auto";
								image.loading = "lazy";
								image.decoding = "async";
								image.referrerPolicy = "no-referrer";
								if (data["ani_thumb"]) {
									const im = data.img;
									const ia = data.ani_thumb;
									image.src = im;
									image.onmouseover = function () {
										image.src = ia;
									};
									image.onmouseout = function () {
										image.src = im;
									};
								} else {
									image.src = data.img;
								}
								a.appendChild(image);
								videoDiv.appendChild(a);
								var contentDiv = document.createElement("div");
								contentDiv.classList.add("endscreen-video-idiv");
								contentDiv.style.verticalAlign = "middle";
								contentDiv.style.display = "table-cell";
								contentDiv.style.paddingLeft = "5px";
								contentDiv.style.paddingRight = "5px";
								var videoTitle = document.createElement("h3");
								videoTitle.style.verticalAlign = "middle";
								videoTitle.style.margin = "0px auto";
								/* Fixes random wrapping issues on Firefox and Chrome */
								videoTitle.style.lineBreak = "anywhere";
								videoTitle.innerHTML = data["text"];
								contentDiv.appendChild(videoTitle);
								var videoDescription = document.createElement("p");
								videoDescription.style.verticalAlign = "bottom";
								videoDescription.style.margin = "0px";
								videoDescription.style.fontSize = "small";
								videoDescription.innerHTML = data["subText"];
								if (data["type"] === "playlist") {
									videoDescription.innerHTML += " &centerdot; PLAYLIST";
								} else if (data["type"] === "website") {
									videoDescription.innerHTML += " &centerdot; EXTERNAL LINK";
								}
								contentDiv.appendChild(videoDescription);
								videoDiv.appendChild(contentDiv);
								eo.appendChild(videoDiv);
							}
						}
					} catch (e) {
						console.error(e);
					}
				}
				function process_related(jsonObject) {
					try {
						const hasGlobalPreferOverride = hasQueryVariable("prefer") && LOCAL_PREFER !== -1;
						const nTubeFilter = nTubeFiltering.createFilter(window.Config);
						const rdiv = id("related_div");
						if (jsonObject["related"] && jsonObject["related"].length == 1) {
							/* Workaround path */
							const singleRelated = jsonObject["related"][0];
							if (singleRelated["workaround"] === true) {
								request(
									"/api/get_page",
									JSON.stringify({ page: "related_workaround", continuation: singleRelated["continuation"], videoId: VIDEO_ID, clientType: singleRelated["clientType"] }),
									function (error) {
										console.error(error);
									},
									function (data) {
										const waObj = JSON.parse(data);
										if (waObj["error"]) {
											console.error("Failed to workaround related.", waObj);
										} else {
											process_related(waObj);
										}
									}
								);
							} else {
								console.error("Got a related without a WORKAROUND flag...", singleRelated);
							}
						} else if (jsonObject["related"] && jsonObject["related"].length > 1) {
							var x = "";
							if (hasGlobalPreferOverride) {
								x += "&prefer=" + LOCAL_PREFER;
							}
							var filteredCountRelated = 0;
							for (var i = 0; i < jsonObject["related"].length; i++) {
								const data = jsonObject["related"][i];
								var videoDiv = document.createElement("div");
								videoDiv.classList.add("related-video");
								videoDiv.classList.add("poly-item");
								videoDiv.classList.add("related-video-poly");
								videoDiv.style.marginBottom = "5px";
								const a = document.createElement("a");
								a.classList.add("related-link-main");
								a.href = data.link;
								const image = document.createElement("img");
								image.style.verticalAlign = "middle";
								image.style.display = "table-row";
								image.style.width = "160px";
								image.style.height = "90px";
								image.loading = "lazy";
								image.decoding = "async";
								image.referrerPolicy = "no-referrer";
								if (data["ani_thumb"]) {
									const im = data.imgURL;
									const ia = data.ani_thumb;
									image.src = im;
									image.onmouseover = function () {
										image.src = ia;
									};
									image.onmouseout = function () {
										image.src = im;
									};
								} else {
									image.src = data.imgURL;
								}
								a.appendChild(image);
								videoDiv.appendChild(a);
								var contentDiv = document.createElement("div");
								contentDiv.classList.add("related-video-idiv");
								contentDiv.style.verticalAlign = "middle";
								contentDiv.style.display = "table-cell";
								contentDiv.style.paddingLeft = "5px";
								contentDiv.style.paddingRight = "5px";
								var videoTitle = document.createElement("h3");
								videoTitle.style.verticalAlign = "middle";
								videoTitle.style.margin = "0px auto";
								/* Fixes random wrapping issues on Firefox and Chrome */
								videoTitle.style.lineBreak = "anywhere";
								videoTitle.innerHTML = data.title;
								contentDiv.appendChild(videoTitle);
								var videoDescription = document.createElement("p");
								videoDescription.style.verticalAlign = "bottom";
								videoDescription.style.margin = "0px";
								videoDescription.style.fontSize = "small";
								videoDescription.innerHTML = data.channel;
								if (data.isPlaylist) {
									videoDescription.innerHTML += " &centerdot; PLAYLIST";
								} else {
									videoDescription.innerHTML += " &centerdot; ";
									if (data.duration === -2) {
										videoDescription.innerHTML += "LIVE";
									} else if (data.duration === -3) {
										videoDescription.innerHTML += "UPCOMING";
									} else if (data.duration === -4) {
										videoDescription.innerHTML += "SHORTS";
									} else {
										videoDescription.innerHTML += seconds2time(data.duration);
									}
									if (data.views && data.views !== -1) {
										videoDescription.innerHTML += " &centerdot; " + numberWithCommas(data.views);
									}
								}
								if (data["isUpNext"]) {
									videoDescription.innerHTML += " &centerdot; Up Next.";
									videoDiv.setAttribute("is-upnext", "true");
								}
								contentDiv.appendChild(videoDescription);
								videoDiv.appendChild(contentDiv);
								if (nTubeFilter.check(data.title, data.channel, false)) {
									videoDiv.style.display = "none";
									videoDiv.style.visibility = "hidden";
									videoDiv.classList.add("force_hidden");
									filteredCountRelated += 1;
								}
								rdiv.appendChild(videoDiv);
							}
							if (filteredCountRelated > 0) {
								id("filtered_related_text").style.display = "";
								id("filtered_related_text").style.visibility = "";
								id("filtered_related_count").innerHTML = filteredCountRelated;
								if (filteredCountRelated == 1) {
									id("filtered_videos_text").innerHTML = "video";
								}
							}
						}
					} catch (e) {
						console.error(e);
					}
				}
				function get_start_timestamp() {
					if (getQueryVariable("time_continue") !== null) {
						try {
							const i = parseInt(getQueryVariable("time_continue"));
							if (i === NaN) return;
							return i;
						} catch (e) {
							return -1;
						}
					} else if (getQueryVariable("t") !== null) {
						try {
							const iTime = parseInt(getQueryVariable("t"));
							if (iTime === NaN) return;
							return iTime;
						} catch (e) {
							return -1;
						}
					} else {
						return -1;
					}
				}
				function process_volume() {
					if (window && window.sessionStorage) {
						const isUsingNPlayer = "mainPlayer" in window;
						const volumePlayerObject = isUsingNPlayer ? id("_secondary_player") : id("_primary_player");
						/* Restore tracked volume. */
						const volumeItem = sessionStorage.getItem("ntube-session-volume");
						if (volumeItem !== null && volumeItem !== undefined) {
							const volumeItemFloat = parseFloat(volumeItem);
							if (volumeItemFloat > 0.0 && volumeItemFloat < 1.0) {
								volumePlayerObject.volume = volumeItemFloat;
								id("volume").value = volumeItemFloat * 100;
								id("volume_label").innerHTML = volumeItemFloat * 100 + "%";
								displayMessage("nTube", "Restored custom volume.", 5000);
							}
						}
						/* Setup volume tracking */
						volumePlayerObject.addEventListener("volumechange", function () {
							sessionStorage.setItem("ntube-session-volume", volumePlayerObject.volume.toString());
						});
					} else {
						console.debug("[process_volume] Not processing volume, missing sessionStorage.");
					}
				}
				function process_query(should_do_timestamps) {
					if (getQueryVariable("audio") !== null) {
						try {
							displayMessage("nTube", "Enabled audio-only mode.", 5000);
							if (ENABLE_DATA_SAVER) {
								id("_primary_player").poster = "https://i.ytimg.com/vi/" + VIDEO_ID + "/sddefault.jpg";
							} else {
								id("_primary_player").poster = "https://i.ytimg.com/vi/" + VIDEO_ID + "/maxresdefault.jpg";
							}
						} catch (e) {
							console.error(e);
						}
					}
					if (should_do_timestamps && get_start_timestamp() != -1) {
						try {
							id("_primary_player").currentTime = get_start_timestamp();
							displayMessage("nTube", "Seeked to " + seconds2time(iTime) + ".", 5000);
						} catch (ex) {
							console.error(ex);
						}
					}
					process_volume();
				}
				function update_md_over_time() {
					if (UPDATE_METADATA_OVER_TIME) {
						console.debug("nTube will update metadata over time. (every 5 minutes)");
						setInterval(function () {
							try {
								console.debug("Updating metadata...");
								request(
									"/api/get_page",
									JSON.stringify({ page: "updated_metadata", id: VIDEO_ID }),
									function (error) {
										console.error("Failed to get updated_metadata!", error);
									},
									function (data) {
										const um = JSON.parse(data);
										if (um["result"]) {
											const newMetadata = um["result"];
											if (newMetadata["title"]) {
												id("video_title").innerHTML = newMetadata["title"];
											}
											if (newMetadata["viewCount"]) {
												id("video_viewcount").innerHTML = numberWithCommas(newMetadata["viewCount"]);
											}
										} else {
											console.error("Failed to find the result for updated metadata!");
											console.debug(data);
										}
									}
								);
							} catch (exce) {
								console.error("Failed to run metadata update loop.", exce);
							}
						}, 300000 /* 5 minutes */);
					}
				}
				function generate_heatmap(jsonObject) {
					if (jsonObject["metadata"] && jsonObject["metadata"]["heatmap"]) {
						const heatmap = jsonObject["metadata"]["heatmap"];
						if (libWeb.ESCompat.checkIfCompatible(5)) {
							loadScripts([libWeb.ESCompat.checkIfCompatible(6) ? "/resources/chart.js" : "/resources/chart.es5.js"], function () {
								const heatmapCanvas = id("heatmap-canvas");
								try {
									const heatmapData = [];
									const heatmapLabels = [];
									const heatMapTimestamps = [];
									for (var inx = 0; inx < heatmap.length; inx++) {
										const heatmapEntry = heatmap[inx];
										if (heatmapEntry["heatmapPointDuration"] === -1) {
											continue;
										} else {
											heatmapData.push(heatmapEntry["heatmapIntensity"] * 100);
											const ents = heatmapEntry["heatmapPointStartMillis"] / 1000;
											const timeStr = ents;
											const en0 = Math.floor(timeStr);
											const en1 = seconds2time(en0);
											heatmapLabels.push(en1);
											heatMapTimestamps.push(ents);
										}
									}
									const chart = new Chart(heatmapCanvas, {
										type: "line",
										data: {
											datasets: [
												{
													data: heatmapData,
													label: "Average Viewer Interaction (%)",
													borderColor: "#00F",
													fill: true,
												},
											],
											labels: heatmapLabels,
										},
										options: {
											responsive: true,
											resizeDelay: 333,
											legend: {
												onHover: function (event, legendItem) {
													heatmapCanvas.style.cursor = "pointer";
												},
											},
											tooltips: {
												mode: "label",
											},
											hover: {
												onHover: function (e, el) {
													heatmapCanvas.style.cursor = el[0] ? "pointer" : "default";
												},
											},
											onClick: function (event, dataArr, source) {
												if (dataArr === null || dataArr === undefined || dataArr.length === 0) {
													return;
												}
												const dataPoint = dataArr[0];
												if (dataPoint === null || dataPoint === undefined) return;
												if (!dataPoint["index"]) return;
												const dataIndex = dataPoint["index"];
												const timeStamp = heatMapTimestamps[dataIndex];
												const correctTimeStamp = Math.floor(timeStamp);
												displayMessage("nTube.", "Seeking to " + seconds2time(correctTimeStamp) + ".", 5000);
												window.yt.www.watch.player.seekTo(correctTimeStamp);
											},
										},
									});
									window.heatmapChart = chart;
									id("video_heatmap_button").style.display = "";
									id("video_heatmap_button").style.visibility = "";
								} catch (_ex) {
									console.error("Failed to create a chart!", _ex);
									const _heatmapError = document.createElement("p");
									_heatmapError.style.textAlign = "center";
									_heatmapError.innerText = "Failed to create heatmap chart, check your browser console for more information.";
									heatmapCanvas.appendChild(_heatmapError);
								}
							});
						} else {
							console.debug("Skipped heatmaps as our charting library wants ES5...");
						}
					}
				}
				function trigger_360_mode(mainPlayer, jsonObject) {
					if (mainPlayer === null || mainPlayer === undefined) {
						console.warn("trigger_360_mode: mainPlayer === [null/undefined]!", arguments);
						return;
					}
					if (jsonObject && jsonObject["metadata"] && jsonObject["metadata"]["is360"]) {
						loadScripts(["https://naver.github.io/egjs-view360/release/latest/dist/view360.pkgd.min.js"], function () {
							mainPlayer.addEventListener("loadedmetadata", function () {
								mainPlayer.style.height = "72px"; // Overflow a bit.
								show(id("-360-video-div"));
								const c = {
									video: mainPlayer,
									useZoom: true,
									canvasClass: "fix-360-viewer",
								};
								if (jsonObject.metadata.isVR180) {
									c["projectionType"] = "cubestrip";
									c["cubemapConfig"] = {
										order: "BLFDRU",
										tileConfig: [{ rotation: 0 }, { rotation: 0 }, { rotation: 0 }, { rotation: 0 }, { rotation: -90 }, { rotation: 180 }],
									};
								} else {
									c["projectionType"] = "stereoequi";
									c["cubemapConfig"] = {
										order: "RLUDFB",
									};
								}
								console.debug("Setting up PanoViewer with config.", c);
								const panoViewer = new eg.view360.PanoViewer(id("-360-video-div"), c);
								panoViewer.on("error", function (c) {
									console.error("panoViewer threw an error!", c);
								});
								panoViewer.on("ready", function (c) {
									console.debug("panoViewer is ready!", c);
								});
								window.panoViewer = panoViewer;
								window.addEventListener("resize", function () {
									panoViewer.updateViewportDimensions();
								});
								displayMessage("nTube: 360", "Entered 360 mode. Use your mouse to move around.", 5000);
								/* Literally the ugliest fix ever also WTF, WHY DID THAT FIX IT */
								panoViewer._activate();
							});
						});
					}
				}
				function process_video(data) {
					const jsonObject = JSON.parse(data);
					window.jsonObject = jsonObject;
					Object.freeze(window.jsonObject);
					run_async(function () {
						try {
							document.body.style.cursor = "";
						} catch (e) {}
					});
					if (jsonObject.error_id) {
						if (ENABLE_CACHE && window.nTube.cache) {
							run_async(function () {
								window.nTube.cache.removeItem(VIDEO_ID);
							});
						}
						const error_id = jsonObject.error_id;
						if (error_id.startsWith("ERROR_VIDEO_")) {
							id("video_div").style.display = "none";
							id("video_div").style.visibility = "hidden";
							id("error_div").style.display = "";
							id("error_div").style.visibility = "";
							id("error_title").innerHTML = "Failed to extract video.";
							id("error_string").innerHTML =
								(jsonObject.error_id === "ERROR_VIDEO_BLOCKED_IN_COUNTRY" ? "nTube failed to extract this video as it is blocked in your country." : "nTube failed to extract this video as it is contained no metadata.") +
								' <br> Message from YouTube: <span style="font-family: monospace;">' +
								jsonObject.error_message +
								"</span>";
						} else if (error_id === "ERROR_UPCOMING_STREAM") {
							id("error_div").style.display = "";
							id("error_div").style.visibility = "";
							id("error_title").innerHTML = "This video or stream isn't live yet.";
							if (jsonObject["metadata"] && jsonObject.metadata["contentStartTime"]) {
								id("error_string").innerHTML = "";
								var countdownRemaining = jsonObject.metadata["contentStartTime"];
								var countdownDiv = document.createElement("div");
								var countdownSpanMain = document.createElement("span");
								var countdownSpan0 = document.createElement("span");
								var countdownSpan1 = document.createElement("span");
								var countdownSpan2 = document.createElement("span");
								const __initial_remaining = ((jsonObject.metadata["contentStartTime"] - Date.now()) / 1000).toFixed(0);
								if (__initial_remaining < 0) {
									window.setTimeout(function () {
										window.location.reload();
									}, 30000);
									countdownSpan0.innerText = "Awaiting video or stream to go live. Refreshing in ";
									countdownSpan1.innerText = "30 seconds";
									countdownSpan2.innerText = ".";
								} else {
									var countdownInterval = window.setInterval(function () {
										const __remaining = ((jsonObject.metadata["contentStartTime"] - Date.now()) / 1000).toFixed(0);
										if (__remaining <= 0) {
											window.location.reload();
											window.clearInterval(countdownInterval);
										} else {
											countdownSpan1.innerText = seconds2time(__remaining);
										}
									}, 1000);
									countdownSpan0.innerText = "This video or stream will be live in ";
									countdownSpan1.innerText = seconds2time(((jsonObject.metadata["contentStartTime"] - Date.now()) / 1000).toFixed(0));
									countdownSpan2.innerText = " from now. (" + new Date(jsonObject.metadata["contentStartTime"]) + ")";
								}
								countdownDiv.appendChild(countdownSpan0);
								countdownDiv.appendChild(countdownSpan1);
								countdownDiv.appendChild(countdownSpan2);
								id("error_string").appendChild(countdownDiv);
							} else {
								id("error_string").innerHTML = jsonObject.error_message;
							}
							if (jsonObject.metadata["chat"]) {
								var s = __nt_init_commentsUI(jsonObject["metadata"]["chat"]["url"], window.Config);
								window.liveChatiFrame = s;
								//s.src = jsonObject["metadata"]["chat"]["url"];
								s.contentWindow.onload = function () {
									window.this = window;
								};
							} else {
								id("video_div").style.display = "none";
								id("video_div").style.visibility = "hidden";
							}
						} else if (error_id !== null && error_id !== "") {
							id("video_div").style.display = "none";
							id("video_div").style.visibility = "hidden";
							id("error_div").style.display = "";
							id("error_div").style.visibility = "";
							id("error_title").innerHTML = "Error: " + jsonObject.error_id;
							id("error_string").innerHTML = jsonObject.error_message;
						}
						run_async(function () {
							if (jsonObject.metadata) {
								document.title = jsonObject.metadata.title + " - nTube";
								id("video_title").innerHTML = jsonObject.metadata.title;
								id("video_duration").innerHTML = seconds2time(jsonObject.metadata.duration);
								id("video_author").innerHTML = jsonObject.metadata.author;
								id("video_author").href = "/channel?c=" + jsonObject.metadata.authorID;
								if (jsonObject.metadata.views == -1) {
									id("video_viewcount").innerHTML = "N/A";
								} else {
									id("video_viewcount").innerHTML = numberWithCommas(jsonObject.metadata.views);
								}
								if (jsonObject.metadata.percentRating) {
									id("video_rating_g").style.width = jsonObject.metadata.percentRating + "%";
								}
								if (jsonObject.metadata.localizedTitle && jsonObject.metadata.localizedTitle !== jsonObject.metadata.title && !DISABLE_LOCALIZED_VIDEO_TEXT) {
									id("video_title_localized").innerHTML = jsonObject.metadata.localizedTitle;
									id("video_title").style.marginTop = "0px";
									show(id("video_title_localized"));
								}
								if (jsonObject.metadata.likeData) {
									// TODO: read le visual option for displaying likes (NTUBE-TODO-LIKES-UI)
									var _likeCount = jsonObject.metadata.likeData["likes"];
									var _dislikeCount = jsonObject.metadata.likeData["dislikes"];
									if (_likeCount > -1 && _dislikeCount > -1) {
										id("video_rating_pre").title = numberWithCommas(_likeCount) + " likes / " + numberWithCommas(_dislikeCount) + " dislikes";
									} else if (_likeCount > -1 && _dislikeCount <= -1) {
										id("video_rating_pre").title = numberWithCommas(_likeCount) + " likes / No dislike data provided.";
									} else if (_likeCount <= -1 && _dislikeCount > -1) {
										id("video_rating_pre").title = "No like data provided / " + numberWithCommas(_dislikeCount) + " dislikes";
									}
								}
								if (jsonObject.metadata.limitedExtractionData && jsonObject.metadata.views == -1) {
									id("video_rating_g").style.backgroundColor = "gray";
								}
								if (jsonObject.metadata.description) {
									id("video_description").innerHTML = base64Decode(jsonObject.metadata.description);
								}
								if (jsonObject.metadata.extended) {
									const e = jsonObject.metadata.extended;
									if (e["publishDate"] && e !== null) {
										id("publish_date_string").innerHTML = e["publishDate"];
									}
									if (e["uploadDate"] && e !== null) {
										id("upload_date_string").innerHTML = e["uploadDate"];
									}
									id("ff_string").innerHTML = e["familyFriendly"] ? "Yes" : "No";
									if (e["rawLoudnessDb"]) {
										id("ldb_date_string").innerHTML = e["rawLoudnessDb"];
									}
								}
							}
						});
						run_async(function () {
							process_related(jsonObject);
						});
					} else {
						if (ENABLE_CACHE && window.nTube.cache) {
							run_async(function () {
								window.nTube.cache.setItem(VIDEO_ID, data, {
									expirationAbsolute: null,
									expirationSliding: 300,
									priority: Cache.Priority.NORMAL,
								});
							});
						}
						run_async(function () {
							document.title = jsonObject.metadata.title + " - nTube";
							id("video_title").innerHTML = jsonObject.metadata.title;
							if (jsonObject.metadata.isLiveStream) {
								id("video_duration").innerHTML = "LIVE";
							} else {
								id("video_duration").innerHTML = seconds2time(jsonObject.metadata.duration);
							}
							id("video_author").innerHTML = jsonObject.metadata.author;
							id("video_author").href = "/channel?c=" + jsonObject.metadata.authorID;
							if (jsonObject.metadata.views == -1) {
								id("video_viewcount").innerHTML = "N/A";
							} else {
								id("video_viewcount").innerHTML = numberWithCommas(jsonObject.metadata.views);
							}
							if (jsonObject.metadata.percentRating) {
								id("video_rating_g").style.width = jsonObject.metadata.percentRating + "%";
							}
							if (jsonObject.metadata.localizedTitle && jsonObject.metadata.localizedTitle !== jsonObject.metadata.title && !DISABLE_LOCALIZED_VIDEO_TEXT) {
								id("video_title_localized").innerHTML = jsonObject.metadata.localizedTitle;
								id("video_title").style.marginTop = "0px";
								show(id("video_title_localized"));
							}
							if (jsonObject.metadata.likeData) {
								// TODO: read le visual option for displaying likes (NTUBE-TODO-LIKES-UI)
								var _likeCount = jsonObject.metadata.likeData["likes"];
								var _dislikeCount = jsonObject.metadata.likeData["dislikes"];
								if (_likeCount > -1 && _dislikeCount > -1) {
									id("video_rating_pre").title = numberWithCommas(_likeCount) + " likes / " + numberWithCommas(_dislikeCount) + " dislikes";
								} else if (_likeCount > -1 && _dislikeCount <= -1) {
									id("video_rating_pre").title = numberWithCommas(_likeCount) + " likes / No dislike data provided.";
								} else if (_likeCount <= -1 && _dislikeCount > -1) {
									id("video_rating_pre").title = "No like data provided / " + numberWithCommas(_dislikeCount) + " dislikes";
								}
								if (ENABLE_DISLIKE_FETCHING) {
									run_async(function () {
										fetchDislikes();
									});
								}
							}
							if (jsonObject.metadata.limitedExtractionData && jsonObject.metadata.views == -1) {
								id("video_rating_g").style.backgroundColor = "gray";
							}
							if (jsonObject.metadata.description) {
								id("video_description").innerHTML = base64Decode(jsonObject.metadata.description);
							}
							if (jsonObject.metadata.tags) {
								id("video_tags").innerHTML = base64Decode(jsonObject.metadata.tags).replaceAll('"', "");
							}
							if (jsonObject.metadata.extended) {
								const e = jsonObject.metadata.extended;
								if (e["publishDate"] && e !== null) {
									id("publish_date_string").innerHTML = e["publishDate"];
								}
								if (e["uploadDate"] && e !== null) {
									id("upload_date_string").innerHTML = e["uploadDate"];
								}
								id("ff_string").innerHTML = e["familyFriendly"] ? "Yes" : "No";
								if (e["rawLoudnessDb"]) {
									id("ldb_date_string").innerHTML = e["rawLoudnessDb"];
								}
							}
							if (jsonObject.metadata.clarifications) {
								const cs = jsonObject.metadata.clarifications;
								const l = id("misc-prompt-ui");
								l.style.display = "";
								l.style.visibility = "";
								for (var i = 0; i < cs.length; i++) {
									const n = cs[i];
									const d = document.createElement("div");
									d.classList.add("poly-item");
									d.style.backgroundColor = "rgba(164, 121, 0, 0.4)";
									const t = document.createElement("h3");
									t.innerHTML = n.title;
									t.style.float = "left";
									t.style.margin = "5px 0px";
									d.appendChild(t);
									if (n["url"] !== null && n["url"] !== undefined && n["url"] !== "null") {
										const t2 = document.createElement("a");
										t2.href = n.url;
										t2.innerHTML = "Link";
										t2.style.float = "right";
										t2.style.border = "1px solid gray";
										t2.style.padding = "3px";
										t2.style.marginTop = "12px";
										t2.style.marginRight = "10px";
										t2.paddingLeft = "15px";
										t2.paddingRight = "15px";
										d.appendChild(t2);
									}
									const t3 = document.createElement("h4");
									t3.style.clear = "both";
									t3.style.margin = "5px 0px";
									t3.innerHTML = n.text;
									d.appendChild(t3);
									const t4 = document.createElement("p");
									t4.innerHTML = n.subText;
									t4.style.margin = "5px 0px";
									d.appendChild(t4);
									l.appendChild(d);
								}
							}
							if (jsonObject.metadata.supertags) {
								var o = "";
								for (var i = 0; i < jsonObject.metadata.supertags.length; i++) {
									const tag = jsonObject.metadata.supertags[i];
									if (i == jsonObject.metadata.supertags.length - 1) {
										o += tag;
									} else {
										o += tag + ", ";
									}
								}
								id("video_super_tags").innerHTML = o;
							}
						});
						if (jsonObject.drm && !ENABLE_DRM_SUPPORT) {
							id("video_div").style.display = "none";
							id("video_div").style.visibility = "hidden";
							id("error_div").style.display = "";
							id("error_div").style.visibility = "";
							id("error_title").innerHTML = "Cannot continue with video playback.";
							id("error_string").innerHTML = "This video uses DRM and you currently have set DRM to be disallowed, therefore nTube cannot continue.";
							throw new Error("Halted video_init as DRM is present and we don't allow it.");
						}
						run_async(function () {
							generate_heatmap(jsonObject);
						});
						run_async(function () {
							if (jsonObject.chapters) {
								const chapters = jsonObject.chapters;
								id("video_chapters_button").style.display = "";
								id("video_chapters_button").style.visibility = "";
								const vc = id("video_chapters");
								vc.innerHTML = "";
								for (var i = 0; i < chapters.length; i++) {
									const chapter = chapters[i];
									const c = document.createElement("div");
									c.classList.add("video-chapter", "poly-item", "video-chapter-poly");
									c.style.marginBottom = "5px";
									c.style.paddingLeft = "0px";
									c.setAttribute("time", chapter.time);
									c.onclick = function () {
										yt.www.watch.player.seekTo(chapter.time / 1000);
										displayMessage("nTube.", "Jumping to chapter '" + chapter.title + "'.", 5000);
									};
									const idiv = document.createElement("div");
									idiv.classList.add("video-chapter-idiv");
									idiv.style.verticalAlign = "middle";
									idiv.style.display = "table-cell";
									idiv.style.paddingLeft = "0px";
									idiv.style.paddingRight = "5px";
									const ct = document.createElement("h3");
									ct.style.verticalAlign = "middle";
									ct.style.margin = "0px auto";
									ct.innerHTML = chapter.title;
									ct.style.paddingLeft = "2px";
									idiv.appendChild(ct);
									const cd = document.createElement("p");
									cd.style.verticalAlign = "bottom";
									cd.style.margin = "0px";
									cd.style.fontSize = "small";
									cd.style.paddingLeft = "2px";
									cd.innerHTML = seconds2time(chapter.time / 1000);
									idiv.appendChild(cd);
									c.appendChild(idiv);
									vc.appendChild(c);
									if (window.nTubeFiltering && window.nTubeFiltering.CHAPTER_FILTERS && containsAny(chapter.title, window.nTubeFiltering.CHAPTER_FILTERS)) {
										// TODO: Add chapter filter implementation
										c.classList.add("video-chapter-unwanted");
										cd.innerHTML += ' &centerdot; <span title="This chapter may contain unwanted content and has been marked as such.">Unwanted?</span>';
									}
									/*const o = document.createElement("li");
								o.innerHTML = seconds2time(chapter.time / 1000) + ": " + chapter.title;
								o.setAttribute("time", chapter.time);
								o.style.textDecoration = "gray underline dotted";
								o.onclick = function() {
									yt.www.watch.player.seekTo((chapter.time / 1000));
								}
								id("video_chapters").appendChild(o);*/
								}
							}
						});
						var mainPlayer = id("_primary_player");
						var audioPlayer = id("_secondary_player");
						const isCandidateForNVPB = PLAYBACK_ENGINE === "nPlayerNX";
						const disablePlayers = ((isMobile && is_iPhoneOS()) || !("MediaSource" in window) || EMULATE_MSE_MISSING) && !isCandidateForNVPB;
						console.debug("isCandidateForNVPB: " + isCandidateForNVPB);
						console.debug("disablePlayers: " + disablePlayers);
						console.debug("isMobileEnv: " + (isMobile && is_iPhoneOS()));
						console.debug("missingMSE: " + !("MediaSource" in window));
						console.debug("PREFER_AAC_OVER_OPUS: " + PREFER_AAC_OVER_OPUS);
						if (disablePlayers) {
							if (!("MediaSource" in window)) {
								console.warn("window.MediaSource is missing!");
							} else {
								console.warn("nTube: iPhone/iPad/Android-(with large buffers) detected, disabling any form of high quality playback.");
								console.debug("MediaSource.value: " + window.MediaSource);
								console.debug("webkitMediaSource.value: " + window.webkitMediaSource);
							}
						}
						if (window.Config && window.Config.appearance.enable_apple_look) {
							id("fruit_loader").style.display = "none";
							id("fruit_loader").style.visibility = "hidden";
						}
						run_async(function () {
							const loop = getQueryVariable("loop");
							if (loop !== null && loop === "1") {
								mainPlayer.loop = true;
								audioPlayer.loop = true;
							}
						});
						run_async(function () {
							if (window.MediaMetadata && "mediaSession" in navigator && !(PLAYBACK_ENGINE === "redwood")) {
								var pp = id("_primary_player");
								if (pp == null) {
									try {
										pp = document.getElementsByClassName("video-stream html5-main-video")[0];
									} catch (e) {}
								}
								if (pp.tagName === "DIV") {
									pp = pp.children[0];
								}
								var artistPayload = jsonObject.metadata.author;
								try {
									artistPayload = artistPayload.replace(" - Topic", "");
								} catch (ex) {}
								var albumPayload = "Powered by nTube.";
								if (jsonObject && jsonObject["playlist"] && jsonObject["playlist"]["name"]) {
									albumPayload = jsonObject["playlist"]["name"] + " · " + albumPayload;
								}
								Object.assign(navigator.mediaSession, {
									metadata: new window.MediaMetadata({
										title: jsonObject.metadata.title,
										artist: artistPayload,
										album: albumPayload,
										artwork: [
											{
												src: "https://i.ytimg.com/vi/" + VIDEO_ID + "/mqdefault.jpg",
												sizes: "320x180",
												type: "image/jpeg",
											},
											{
												src: "https://i.ytimg.com/vi/" + VIDEO_ID + "/default.jpg",
												sizes: "120x90",
												type: "image/jpeg",
											},
										],
									}),
								});
								navigator.mediaSession.setActionHandler("play", function () {
									if ("mainPlayer" in window) {
										mainPlayer.play();
									} else {
										pp.play();
									}
									navigator.mediaSession.playbackState = "playing";
								});
								navigator.mediaSession.setActionHandler("pause", function () {
									if ("mainPlayer" in window) {
										mainPlayer.pause();
									} else {
										pp.pause();
									}
									navigator.mediaSession.playbackState = "paused";
								});
								function updatePositionState() {
									navigator.mediaSession.setPositionState({
										duration: mainPlayer.duration,
										playbackRate: mainPlayer.playbackRate,
										position: mainPlayer.currentTime,
									});
								}
								navigator.mediaSession.setActionHandler("seekbackward", function () {
									if ("mainPlayer" in window) {
										mainPlayer.seek(mainPlayer.getTime() - 5);
									} else {
										pp.currentTime -= 5;
									}
									try {
										updatePositionState();
									} catch (_ex) {}
								});
								navigator.mediaSession.setActionHandler("seekforward", function () {
									if ("mainPlayer" in window) {
										mainPlayer.seek(mainPlayer.getTime() + 5);
									} else {
										pp.currentTime += 5;
									}
									try {
										updatePositionState();
									} catch (_ex) {}
								});
								try {
									updatePositionState();
									navigator.mediaSession.playbackState = "playing";
								} catch (_ex) {}
								if (jsonObject["playlist"] && jsonObject["playlist"]["next"]) {
									navigator.mediaSession.setActionHandler("nexttrack", function () {
										if (jsonObject["playlist"]) {
											if (jsonObject["playlist"]["next"]) {
												window.location = jsonObject.playlist.next.link;
												return;
											}
										}
										window.location = i0.link;
										return;
									});
								} else if (jsonObject["related"] && jsonObject["related"].length > 0) {
									const i0 = jsonObject["related"][0];
									if (i0["isUpNext"] === true) {
										navigator.mediaSession.setActionHandler("nexttrack", function () {
											window.location = i0.link;
											return;
										});
									}
								}
							}
						});
						run_async(function () {
							if (jsonObject.metadata["chat"]) {
								var s = __nt_init_commentsUI(jsonObject["metadata"]["chat"]["url"], window.Config);
								window.liveChatiFrame = s;
								s.contentWindow.onload = function () {
									window.this = window;
								};
							}
						});
						run_async(function () {
							process_endscreen(jsonObject);
						});
						run_task(function () {
							function __init_dash_events(player) {
								player.on(dashjs.MediaPlayer.events.QUALITY_CHANGE_REQUESTED, function () {
									try {
										var currentQualityIndex = player.getQualityFor("video");
										var currentQualityObject = player.getBitrateInfoListFor("video")[currentQualityIndex];
										//id("quality_dropdown_string").innerHTML = (currentQualityObject.height + "p");
									} catch (e) {
										console.error(e);
										id("quality_dropdown_string").innerHTML = mainPlayer.videoHeight + "p";
									}
								});
								player.on(dashjs.MediaPlayer.events.QUALITY_CHANGE_RENDERED, function () {
									try {
										var currentQualityIndex = player.getQualityFor("video");
										var currentQualityObject = player.getBitrateInfoListFor("video")[currentQualityIndex];
										id("quality_dropdown_string").innerHTML = currentQualityObject.height + "p";
									} catch (e) {
										console.error(e);
										id("quality_dropdown_string").innerHTML = mainPlayer.videoHeight + "p";
									}
								});
								player.on(dashjs.MediaPlayer.events.ERROR, function (data) {
									console.error("[dashjs] Error fired!", arguments);
									__generate_playback_error(lzbase62.compress(data) + " (ERROR_DASH_EVENT)");
								});
							}
							const isLiveStream = jsonObject.metadata && jsonObject.metadata.isLiveStream;
							if (ENABLE_MPD_DASH && !disablePlayers && ENABLE_CACHE && window.nTube && window.nTube.cache) {
								run_async(function () {
									window.nTube.cache.removeItem(VIDEO_ID);
								});
							}
							if (isValidObject(jsonObject.videos.preferred.video) && isValidObject(jsonObject.videos.preferred.audio) && supportsPlayer("nMuxer", disablePlayers, isLiveStream, ENABLE_IOS_HLS)) {
								var can_use_numxer = !disablePlayers; //jsonObject.metadata.duration < 694; // 694s -> 11:34 (Max buffer size)
								var core_nmuxer_supported = window.MediaSource && PLAYBACK_ENGINE === "nMuxer";
								if (core_nmuxer_supported && can_use_numxer) {
									displayMessage("nTube: WARNING", "nMuxer is currently experimental, your mileage may vary.", 5000);
									loadScripts(["/resources/nplayer_mse/nMuxer.js"], function () {
										var vb = jsonObject.videos.videoStreams[jsonObject.videos.preferred.video];
										var va = jsonObject.videos.audioStreams[vb.mse_pair];
										if (va === undefined) {
											va = jsonObject.videos.audioStreams[vb.mse_pair - 1];
										}
										const mxi = [
											{
												url: vb.proxied_url,
												bitrate: vb.bitrate,
												length: vb.size,
												mime: vb.mime,
												coreData: {
													init: vb.init,
													index: vb.index,
												},
											},
											{
												url: va.proxied_url,
												bitrate: va.bitrate,
												length: va.size,
												mime: va.mime,
												coreData: {
													init: va.init,
													index: va.index,
												},
											},
										];
										window.nMuxerInitData = mxi;
										var x = nMuxer(mxi);
										mainPlayer.src = URL.createObjectURL(x.mediaSource);
										mainPlayer.onerror = function () {
											console.error(mainPlayer.error);
										};
										//ms.addEventListener('sourceopen', sourceOpen);
										if (ENABLE_EQUALIZER) {
											createVisualiser(mainPlayer);
										}
										process_query(false);
									});
									window.nTubeVideo = { syncMethod: "nmuxer" };
								} else if (window.Config && PLAYBACK_ENGINE === "dash.js" && jsonObject.videos.muxedPayload && supportsPlayer("dash", disablePlayers, isLiveStream, ENABLE_IOS_HLS)) {
									loadScripts(["/resources/dash.js"], function () {
										id("quality_dropdown").style.display = "";
										id("quality_dropdown").style.visibility = "";
										var settings = {
											settings: {
												streaming: {
													fastSwitchEnabled: !window.isIE11,
													stableBufferTime: 15,
													bufferToKeep: getBufferSize(),
													bufferTimeAtTopQualityLongForm: getHQBufferSize(),
													scheduleWhilePaused: false,
													retryIntervals: {
														InitializationSegment: 133,
														IndexSegment: 133,
														MediaSegment: 133,
														BitstreamSwitchingSegment: 133,
														other: 133,
													},
													retryAttempts: {
														InitializationSegment: 16,
														IndexSegment: 16,
														MediaSegment: 64,
														BitstreamSwitchingSegment: 64,
														other: 32,
													},
												},
											},
										};
										const player = dashjs.MediaPlayer().create(settings);
										//player.getDebug().setLogLevel(dashjs.Debug.LOG_LEVEL_DEBUG); DEBUGGING_FIXED
										window.ndashPlayer = player;
										//"data:application/dash+xml;base64," +
										player.initialize(mainPlayer, "/b64_dec?td=" + jsonObject.videos.muxedPayload + "&dashMime", true);
										if (jsonObject.drm && jsonObject.drm.drmTypes) {
											var protectionData = {};
											for (var i = 0; i < jsonObject.drm.drmTypes.length; i++) {
												const drm = jsonObject.drm.drmTypes[i];
												if (drm["family"] === "WIDEVINE") {
													const o = { serverURL: drm["url"], httpRequestHeaders: {} };
													if (jsonObject.drm.drmConfig && jsonObject.drm.drmConfig["widevineServiceCert"]) {
														o["serverCertificate"] = RedwoodDRM.decipherServerCertificate(jsonObject.drm.drmConfig["widevineServiceCert"]);
													}
													protectionData["com.widevine.alpha"] = o;
												} else if (drm["family"] === "PLAYREADY") {
													protectionData["com.microsoft.playready"] = { serverURL: drm["url"] };
												} else {
													console.warn("nTube::DRM: Unknown family: " + drm["family"]);
												}
											}
											player.setProtectionData(protectionData);
										}
										console.debug("ndashPlayer: Using buffer size of " + getBufferSize() + " seconds.");
										__init_dash_events(player);
										var __n = 0;
										if (LOCAL_PREFER != null) {
											__n = LOCAL_PREFER;
										} else if (GLOBAL_PREFER != -1) {
											__n = GLOBAL_PREFER;
										}
										player.on(dashjs.MediaPlayer.events.STREAM_INITIALIZED, function () {
											console.debug("nDashJS: Bitrates: " + player.getBitrateInfoListFor("video"));
											console.debug("nDashJS: Current Quality: " + player.getQualityFor("video"));
											var br = player.getBitrateInfoListFor("video");
											if (DASH_JS_ENABLE_QUALITY_ENFORCEMENT) {
												console.debug("[ndashPlayer] Enforcing initial quality.");
												for (var i = 0; i < br.length; i++) {
													var q = br[i].height;
													var next = br[i + 1];
													if (q === __n) {
														if (next !== undefined && next !== null) {
															// fix to get 60 fps to be preferred
															var qn = next.height;
															if (q === qn) {
																player.setQualityFor("video", i + 1);
																break;
															}
														}
														player.setQualityFor("video", i);
														break;
													}
												}
											}
											if (ENABLE_EQUALIZER) {
												createVisualiser(mainPlayer);
											}
											process_query(true);
											trigger_360_mode(mainPlayer, jsonObject);
										});
										mainPlayer.play();
									});
									window.nTubeVideo = { syncMethod: "dash" };
									/* videojs was implemented in 1.5-rc3 and removed in 1.5-rc4 */
								} else if (window.Config && PLAYBACK_ENGINE === "rxplayer" && jsonObject.videos.muxedPayload && supportsPlayer("rx-player", disablePlayers, isLiveStream, ENABLE_IOS_HLS)) {
									const hasSurroundAudio = jsonObject.videos.audioStreams.some(function (e) {
										return e["surroundAudio"];
									});
									if (hasSurroundAudio) {
										console.debug("Preferring AAC over Opus as it has the SURROUND_AUDIO flag present.");
									}
									loadScripts(["/resources/rx-player.min.js"], function () {
										const rx_cfg = {
											videoElement: mainPlayer,
											stopAtEnd: false,
											throttleVideoBitrateWhenHidden: true,
											wantedBufferAhead: getBufferSize(),
											wasmUrl: "/resources/mpd-parser.wasm",
											preferredAudioTracks: [
												{
													codec: {
														/* DTS is nice but good luck finding a browser that supports it lol */ test: /dtse/,
														all: true,
													},
												},
												{
													codec: {
														/* EAC3 > AC3 */ test: /ec-3/,
														all: true,
													},
												},
												{
													codec: {
														/* Totally not Dolby [copyright] Audio */ test: /ac-3/,
														all: true,
													},
												},
											],
										};
										if (PREFER_AAC_OVER_OPUS || hasSurroundAudio) {
											rx_cfg["preferredAudioTracks"].push({
												codec: {
													test: /mp4a/,
													all: true,
												},
											});
											rx_cfg["preferredAudioTracks"].push({
												codec: {
													test: /opus/,
													all: true,
												},
											});
										} else {
											rx_cfg["preferredAudioTracks"].push({
												codec: {
													/* Opus provides greater audio quality than AAC-LC */ test: /opus/,
													all: true,
												},
											});
											rx_cfg["preferredAudioTracks"].push({
												codec: {
													/* Still use AAC-LC for other devices */ test: /mp4a/,
													all: true,
												},
											});
										}
										if (DASH_JS_ENABLE_QUALITY_ENFORCEMENT) {
											rx_cfg["initialVideoBitrate"] = 3571034;
										}
										const player = new RxPlayer(rx_cfg);
										window.playerInstance = player;
										const rx_player_exts = {};
										if (nTubeNext.Platform.is("feature=web_workers")) {
											rx_player_exts["workerUrl"] = "/resources/rx-player-worker.js";
										}
										if (nTubeNext.Platform.is("feature=wasm")) {
											rx_player_exts["dashWasmUrl"] = "/resources/mpd-parser.wasm";
										}
										player
											.attachWorker(rx_player_exts)
											.then(function () {
												console.debug("[RxPlayer] Attached worker and/or WASM successfully.");
											})
											.catch(function (_err) {
												console.error("[RxPlayer] Failed to invoke attachWorker. (FALLBACK_TO_ST)", _err);
											});
										const payload = {
											url: "/b64_dec?td=" + jsonObject.videos.muxedPayload + "&dashMime",
											transport: "dash",
											networkConfig: {
												segmentRetry: 16,
												manifestRetry: 6,
												segmentRequestTimeout: 34000,
												manifestRequestTimeout: 30000,
											},
											autoPlay: true,
										};
										if (REDUCE_QUALITY_FOR_AV1) {
											payload["onCodecSwitch"] = "reload";
										}
										if (get_start_timestamp() != -1) {
											payload["startAt"] = {
												position: get_start_timestamp(),
											};
										}
										player.addEventListener("error", function (err) {
											console.error("The content stopped with the following error", err);
											__generate_playback_error(lzbase62.compress(err) + " (ERROR_RXPLAYER_PLAYBACK)");
										});
										player.addEventListener("availableAudioTracksChange", function (_ignored) {
											const _rx_tracks = playerInstance.getAvailableAudioTracks();
											if (_rx_tracks !== null && _rx_tracks !== undefined && _rx_tracks.length > 2) {
												show(id("--new-cfg-tab-locale-btn"));
												const _rx_list = id("_ntube_audio_locale");
												_rx_list.innerHTML = "";
												for (var idx = 0; idx < _rx_tracks.length; idx++) {
													const _rx_track = _rx_tracks[idx];
													const _rx_opt = document.createElement("option");
													_rx_opt.setAttribute("idx", idx);
													_rx_opt.setAttribute("id", _rx_track["id"]);
													_rx_opt.innerText = _rx_track["normalized"].replaceAll("&nbsp;", " ");
													_rx_opt.innerText += " (" + _rx_track["representations"][0]["codec"] + ")";
													if (_rx_track["active"] === true) {
														_rx_opt.setAttribute("default", true);
														_rx_opt.setAttribute("selected", true);
														_rx_opt.innerText += " (default)";
													}
													_rx_list.appendChild(_rx_opt);
												}
												_rx_list.addEventListener("change", function () {
													var _opt = _rx_list["selectedOptions"][0];
													if (_opt !== null && _opt !== undefined) {
														var id = _opt.getAttribute("id");
														playerInstance.setAudioTrack(id);
														displayMessage("Locale.", "Requesting audio track change...", 2500);
													}
												});
											}
										});
										if (jsonObject.drm && jsonObject.drm.drmTypes) {
											payload["keySystems"] = [];
											for (var i = 0; i < jsonObject.drm.drmTypes.length; i++) {
												const drm = jsonObject.drm.drmTypes[i];
												if (drm["family"] === "WIDEVINE") {
													try {
														const x = {
															type: "widevine",
															getLicense: function (challenge) {
																return new Promise(function (resolve, reject) {
																	const xhr = new XMLHttpRequest();
																	xhr.open("POST", drm["url"], true);
																	xhr.onerror = function (err) {
																		const error = new Error("Request error: " + err.toString());
																		reject(err);
																	};
																	xhr.onload = function (evt) {
																		if (xhr.status >= 200 && xhr.status < 300) {
																			const license = evt.target.response;
																			resolve(license);
																		} else if (xhr.status >= 500 && xhr.status < 600) {
																			const error = new Error("The license server had a problem and" + "responded with " + xhr.status + " HTTP " + "error. We will now fallback to another" + "quality.");
																			error.noRetry = true;
																			error.fallbackOnLastTry = true;
																			reject(error);
																		} else {
																			const error1 = new Error("getLicense's request finished with a " + xhr.status + " HTTP error");
																			reject(error1);
																		}
																	};
																	xhr.responseType = "arraybuffer";
																	xhr.send(challenge);
																});
															},
															fallbackOn: {
																keyInternalError: true,
																keyOutputRestricted: true,
															},
														};
														if (jsonObject.drm.drmConfig && jsonObject.drm.drmConfig["widevineServiceCert"]) {
															x["serverCertificate"] = RedwoodDRM.decipherServerCertificate(jsonObject.drm.drmConfig["widevineServiceCert"]);
															console.debug("[nTube::DRM] Deciphered server certificate.", x["serverCertificate"]);
														}
														payload["keySystems"].push(x);
													} catch (e) {
														console.error("Failed to add DRM[widevine]!", e);
													}
												} else if (drm["family"] === "PLAYREADY") {
													try {
														payload["keySystems"].push({
															type: "playready",
															getLicense: function (challenge) {
																return new Promise(function (resolve, reject) {
																	const xhr = new XMLHttpRequest();
																	xhr.open("POST", drm["url"], true);
																	xhr.onerror = function (err) {
																		const error = new Error("Request error: " + err.toString());
																		reject(err);
																	};
																	xhr.onload = function (evt) {
																		if (xhr.status >= 200 && xhr.status < 300) {
																			const license = evt.target.response;
																			resolve(license);
																		} else if (xhr.status >= 500 && xhr.status < 600) {
																			const error = new Error("The license server had a problem and" + "responded with " + xhr.status + " HTTP " + "error. We will now fallback to another" + "quality.");
																			error.noRetry = true;
																			error.fallbackOnLastTry = true;
																			reject(error);
																		} else {
																			const error2 = new Error("getLicense's request finished with a " + xhr.status + " HTTP error");
																			reject(error2);
																		}
																	};
																	xhr.responseType = "arraybuffer";
																	xhr.send(challenge);
																});
															},
															fallbackOn: {
																keyInternalError: true,
																keyOutputRestricted: true,
															},
														});
													} catch (e) {
														console.error("Failed to add DRM[playready]!", e);
													}
												} else {
													console.warn("nTube::DRM: Unknown family: " + drm["family"]);
												}
											}
										}
										player.loadVideo(payload);
										process_query(false);
										trigger_360_mode(mainPlayer, jsonObject);
									});
									window.nTubeVideo = { syncMethod: "rxplayer" };
								} else if (PLAYBACK_ENGINE === "redwood") {
									id("actual-primary-video-div").innerHTML = "";
									id("actual-primary-video-div").id = "player-api";
									var vjs_css = document.createElement("link");
									vjs_css.href = "/resources/redwood/player.css";
									vjs_css.rel = "stylesheet";
									vjs_css.type = "text/css";
									vjs_css.media = "all";
									document.head.appendChild(vjs_css);
									window._yt_player = window._yt_player || {};
									try {
										hide(id("button-cinema-mode"));
										id("button-share-video").style.marginRight = "10px";
									} catch (e) {}
									id("player-api").innerHTML = "<script>if (window.ytcsi) {window.ytcsi.tick(\"cfg\", null, '');}<\/script>";
									loadScripts(["/resources/redwood/redwood_preprocessor.js", "/resources/redwood/youtube_base.js", "/resources/redwood/redwood.js"], function () {
										window.ytObject = Redwood.initPlayer(VIDEO_ID, jsonObject);
										id("player-api").style.height = "";
										const sys_non_chrome = typeof InstallTrigger === "undefined";
										if (sys_non_chrome) {
											id("player-api").style.maxHeight = "85vh";
										}
										var yt_fixes = document.createElement("style");
										// FIXME-REDWOOD: top 0px !important fixes but breaks non standard height videos.
										// height: max-content !important; height: -webkit-fill-available !important;
										// width: auto !important;
										// height: fill-available !important; height: auto !important;
										yt_fixes.innerHTML =
											".video-stream {width: auto !important; max-width: 100% !important; bottom: 0px !important; left: 0px !important;" +
											" height: 100% !important; margin: 0 auto; top: 0px !important; " +
											" max-height: 100%; } .ytp-cued-thumbnail-overlay-image {z-index: 11;} .html5-video-container {height: 100%;} ";
										if (sys_non_chrome) {
											yt_fixes.innerHTML += " .html5-video-player, .ytp-contextmenu {height: 85vh;}";
										}
										document.head.appendChild(yt_fixes);
										if (jsonObject.playlist) {
											document.getElementsByClassName("video-stream html5-main-video")[0].addEventListener("ended", function () {
												window.location = jsonObject.playlist.next.link;
											});
										}
										if (ENABLE_EQUALIZER) {
											createVisualiser(document.getElementsByClassName("video-stream html5-main-video")[0]);
										}
										try {
											process_query(false);
											waitForElementToDisplay(
												".html5-video-info-panel-content",
												function () {
													var o = document.getElementsByClassName("html5-video-info-panel-content")[0];
													var e = document.createElement("div");
													var y = document.createElement("div");
													y.innerHTML = "Redwood Version";
													e.appendChild(y);
													var n = document.createElement("span");
													n.innerHTML = Redwood.version;
													e.appendChild(n);
													o.appendChild(e);
												},
												500,
												15000
											);
										} catch (e) {
											console.error(e);
										}
									});
									window.nTubeVideo = { syncMethod: "redwood" };
								} else {
									if (core_nmuxer_supported && !can_use_numxer) {
										var error = id("error_div");
										error.style.display = "";
										error.style.visibility = "";
										id("error_string").innerHTML = "nMuxer cannot process that long of a video, falling back to nPlayer.";
										window.setTimeout(function () {
											error.style.display = "none";
											error.style.visibility = "hidden";
										}, 6000);
									}
									if (isLiveStream || ENABLE_IOS_HLS) {
										var videoURL = jsonObject.videos.combinedStreams[jsonObject.videos.preferred.comb].proxied_url;
										if (!ENABLE_IOS_HLS) {
											run_promise(function () {
												update_md_over_time();
											});
										}
										__init_hls_js(mainPlayer, videoURL, jsonObject.metadata.isLowLatencyStream);
									} else if ((disablePlayers || isMobile || window.is_iPhoneOS()) && !isCandidateForNVPB) {
										var fbobj = jsonObject.videos.combinedStreams[jsonObject.videos.preferred.comb];
										var fburl = fbobj.proxied_url;
										if (fbobj["size"] && fbobj["size"] > 0) {
											fburl += "&_fclen=" + fbobj.size;
										}
										console.debug("Phone Video URL: " + fburl);
										mainPlayer.src = fburl;
										mainPlayer.controls = true;
										window.nTubeVideo = { syncMethod: "fallback" };
										process_query(false);
									} else {
										var blockCorrection = false;
										mainPlayer.setAttribute("mediagroup", "__nplayernx_compat");
										audioPlayer.setAttribute("mediagroup", "__nplayernx_compat");
										window.mainPlayer = window.nPlayerNX(mainPlayer, audioPlayer);
										try {
											show(id("--new-cfg-tab-video-btn"));
										} catch (e) {}
										var nextVideoTest = false;
										mainPlayer.addEventListener("error", function (event) {
											console.error("[nTube] Video playback error occured!");
											console.error(event);
											var ve = mainPlayer.error;
											var videoSelect = id("_ntube_video_qualities");
											if (ve.code === 4 && !nextVideoTest && !blockCorrection) {
												// Codec error
												try {
													try {
														window.mainPlayer.applySource(
															jsonObject.videos.videoStreams[jsonObject.videos.preferred.video - 1].proxied_url,
															jsonObject.videos.audioStreams[jsonObject.videos.preferred.audio - 1].proxied_url
														);
													} catch (e) {
														window.mainPlayer.applySource(jsonObject.videos.combinedStreams[jsonObject.videos.preferred.comb].proxied_url, null);
													}
													var error = id("error_div");
													error.style.display = "";
													error.style.visibility = "";
													id("error_string").innerHTML = "nTube failed to play a video source, trying the next source. (MP4->WebM)";
													window.setTimeout(function () {
														error.style.display = "none";
														error.style.visibility = "hidden";
													}, 6000);
													nextVideoTest = true;
													videoSelect.selectedIndex += 1;
												} catch (e) {
													console.error(e);
													nextVideoTest = true;
												}
											}
										});
										window.nTubeVideo = { syncMethod: "nplayernx" };
										process_query(false);
									}
									mainPlayer.controls = true;
									blockCorrection = true;
								}

								try {
									if (jsonObject.metadata.is360) {
										mainPlayer.crossOrigin = "anonymous";
									}
									if (window.mainPlayer) {
										if (jsonObject.metadata.is360 && ENABLE_360_SUPPORT) {
											mainPlayer.src = jsonObject.videos.videoStreams[jsonObject.videos.preferred.video].proxied_url;
										} else {
											mainPlayer.src = jsonObject.videos.videoStreams[jsonObject.videos.preferred.video].proxied_url;
										}
										audioPlayer.src = jsonObject.videos.audioStreams[jsonObject.videos.preferred.audio].proxied_url;
										window.mainPlayer.play();
										if (ENABLE_EQUALIZER) {
											createVisualiser(audioPlayer);
										}
									}
									try {
										mainPlayer.controls = true;
									} catch (e) {
										console.error("__init::post -> set controls failed.\n" + e);
									}
									if (jsonObject.metadata.is360 && PLAYBACK_ENGINE !== "redwood") {
										if (window.ndashPlayer) {
											window.ndashPlayer.updateSettings({
												streaming: {
													fastSwitchEnabled: false,
												},
											});
										}
										// Replaced by trigger_360_mode()
									}
								} catch (e) {
									console.error(e);
									if (window.mainPlayer) {
										window.mainPlayer.applySource(jsonObject.videos.combinedStreams[jsonObject.videos.preferred.comb].proxied_url, null);
										window.mainPlayer.play();
									}
									var error = id("error_div");
									error.style.display = "";
									error.style.visibility = "";
									id("error_string").innerHTML = "nTube didn't find any video streams, falling back to combined streams.";
								}
							} else {
								if (jsonObject.videos.combinedStreams === null || jsonObject.videos.combinedStreams.length === 0) {
									__generate_playback_error("COMBINED_STREAMS_MISSING_AT_FALLBACK");
									throw new Error("E:CANNOT_FALLBACK (msg: combinedStreams is missing)");
								}
								var videoURL = jsonObject.videos.combinedStreams[jsonObject.videos.preferred.comb].proxied_url;
								if (videoURL === null || videoURL === undefined) {
									log.warn("videoURL is null! [or undefined] This isn't very good...", videoURL);
								}
								if ((videoURL.endsWith(".m3u8") || jsonObject.videos.combinedStreams[jsonObject.videos.preferred.comb].liveStream) && (ENABLE_IOS_HLS ? !disablePlayers : true)) {
									run_promise(function () {
										update_md_over_time();
									});
									__init_hls_js(mainPlayer, videoURL, jsonObject.metadata.isLowLatencyStream);
								} else {
									var fbobj = jsonObject.videos.combinedStreams[jsonObject.videos.preferred.comb];
									var fburl = fbobj.proxied_url;
									if (fbobj["size"] && fbobj["size"] > 0) {
										fburl += "&_fclen=" + fbobj["size"];
									}
									mainPlayer.src = fburl;
									mainPlayer.controls = true;
									window.nTubeVideo = { syncMethod: "fallback" };
								}
							}
						}, libWeb.TaskDispatcher.TaskPriority.VISIBLE_TASK);
						run_async(function () {
							if (jsonObject.playlist) {
								id("__pl_goto_el").href = "/playlist?list=" + getQueryVariable("list");
								id("__pl_upnext").style.display = "";
								id("__pl_upnext").style.visibility = "";
								id("__pl_upnext_text").innerHTML = jsonObject.playlist.next.title;
								id("__pl_upnext_author_text").innerHTML = jsonObject.playlist.next.author;
								id("__pl_upnext_img").src = jsonObject.playlist.next.thumbnail;
								if (jsonObject.playlist.name) {
									id("__pl_header").innerHTML = "Playlist: " + jsonObject.playlist.name;
								}
								if (jsonObject.playlist.index) {
									id("__pl_index_div").style.display = "";
									id("__pl_index_div").style.visibility = "";
									id("__pl_index").innerHTML = jsonObject.playlist.index;
								}
								if (mainPlayer !== null && mainPlayer !== undefined) {
									mainPlayer.addEventListener("ended", function () {
										window.location = jsonObject.playlist.next.link;
									});
									if (ENABLE_CACHE && window.nTube && window.nTube.cache) {
										var hasPreCached = false;
										mainPlayer.addEventListener("timeupdate", function () {
											if (mainPlayer.duration - mainPlayer.currentTime <= 10 && !hasPreCached) {
												const id = getQueryVariableString(jsonObject.playlist.next.link, "v");
												preCacheID(id, jsonObject.playlist.next.link);
												hasPreCached = true;
											}
										});
									}
								}
								id("__pl_upnext_skip").href = jsonObject.playlist.next.link;
								if (window.Config) {
									if (window.Config.playback.enablePlaylistNotifications) {
										sendMessage("nTube: Now Playing.", jsonObject.metadata.title, 5000, "/logo-small.png");
									}
								}
							}
						});
						run_async(function () {
							if (BLOCK_SPONSORS || getQueryVariable("enableSponsorBlock") !== null) {
								request(
									"/api/get_sponsors?v=" + VIDEO_ID,
									function (error) {
										console.error("Failed to get sponsors.");
										console.error(error);
									},
									function (spons_data) {
										const d = JSON.parse(spons_data);
										const l = d.length;
										if (l > 0) {
											console.debug("[nTube.sponsorBlock] Found sponsors!");
											var pp = id("_primary_player");
											if (pp == null || PLAYBACK_ENGINE === "redwood") {
												try {
													pp = document.getElementsByClassName("video-stream html5-main-video")[0];
												} catch (e) {}
											}
											if (pp === null || pp === undefined) {
												console.warn("Failed to set sponsor skipping!");
											} else {
												if (pp.tagName === "DIV") {
													pp = pp.children[0];
												}
												pp.addEventListener("timeupdate", function () {
													const time = pp.currentTime;
													const duration = pp.duration;
													for (var _i = 0; _i < l; _i++) {
														const i = _i;
														const isWithinEnd = duration - time <= 1;
														const isInRange = time > d[i].start && time < d[i].end;
														if (isInRange && !isWithinEnd) {
															console.debug("[nTube.sponsorBlock] Skipping sponsored segment. " + d[i].start + " -> " + d[i].end);
															console.debug("currentTime: " + pp.currentTime);
															if (window.mainPlayer) {
																window.mainPlayer.seek(d[i].end + 0.1);
															} else {
																pp.currentTime = d[i].end + 0.1;
															}
															displayMessage("SponsorBlocker", "Skipped a sponsored segment.", 2000);
															break;
														}
													}
												});
											}
										} else {
											console.debug("[nTube.sponsorBlock] Didn't find any sponsors...did we time out?");
										}
									}
								);
							}
						});
						run_async(function () {
							if (jsonObject.videos) {
								var videoSelect = id("_ntube_video_qualities");
								videoSelect.innerHTML = "";
								var combined = document.createElement("optgroup"),
									videoCombined = document.createElement("optgroup"),
									videoSeperate = document.createElement("optgroup"),
									audioSeperate = document.createElement("optgroup");
								combined.label = "Fallback Streams";
								videoCombined.label = "Combined Streams";
								videoSeperate.label = "Video Streams";
								audioSeperate.label = "Audio Streams";
								for (var i = 0; i < jsonObject.videos.combinedStreams.length; i++) {
									try {
										const stream = jsonObject.videos.combinedStreams[i];
										const opt = document.createElement("option");
										opt.setAttribute("dataType", "combinedSingle");
										opt.setAttribute("url", stream.proxied_url);
										opt.setAttribute("proxied_url", stream.proxied_url);
										opt.setAttribute("listAttr", i);
										opt.setAttribute("listAttr", "comb");
										opt.setAttribute("codec", stream.pmime);
										opt.innerHTML = stream.quality + "p" + stream.fps + "&nbsp;";
										if (stream.codec === "MPEG4/H.264") {
											opt.innerHTML += "[MP4]";
										} else if (stream.codec === "MPEG4+WEBM/AV1") {
											opt.innerHTML += "[AV1]";
										} else if (stream.codec === "WEBM/VP8+9") {
											opt.innerHTML += "[WebM]";
										} else if (stream.codec === "3GPP/MPEG4") {
											opt.innerHTML += "[3GPP]";
										}
										combined.appendChild(opt);
									} catch (e) {
										console.error(e);
									}
								}
								for (var i = 0; i < jsonObject.videos.videoStreams.length; i++) {
									try {
										const stream0 = jsonObject.videos.videoStreams[i];
										const opt0 = document.createElement("option");
										opt0.setAttribute("dataType", "combinedPair");
										opt0.setAttribute("url", stream0.proxied_url);
										opt0.setAttribute("pairURL", jsonObject.videos.audioStreams[stream0.audioPair].proxied_url);
										opt0.setAttribute("pair_proxied_url", jsonObject.videos.audioStreams[stream0.audioPair].proxied_url);
										opt0.setAttribute("proxied_url", stream0.proxied_url);
										opt0.setAttribute("listAttr", i);
										opt0.setAttribute("listAttr", "video");
										opt0.setAttribute("codec", stream0.pmime + ", " + jsonObject.videos.audioStreams[stream0.audioPair].pmime);
										opt0.innerHTML = stream0.quality + "p" + stream0.fps + "&nbsp;";
										var pair = jsonObject.videos.audioStreams[stream0.audioPair];
										if (stream0.codec === "MPEG4/H.264") {
											opt0.innerHTML += "[MP4";
										} else if (stream0.codec === "MPEG4+WEBM/AV1") {
											opt0.innerHTML += "[AV1";
										} else if (stream0.codec === "WEBM/VP8+9") {
											opt0.innerHTML += "[WebM";
										}
										if (pair.codec === "MPEG4/AAC") {
											opt0.innerHTML += ", AAC" + (pair.surroundAudio ? "+S" : "") + "]";
										} else if (pair.codec === "WEBM/VORBIS") {
											opt0.innerHTML += ", Vorbis]";
										} else if (pair.codec === "WEBM/OPUS") {
											opt0.innerHTML += ", Opus]";
										} else if (pair.codec === "MPEG3") {
											opt0.innerHTML += ", MP3]";
										} else if (pair.codec === "MPEG4/AC3") {
											opt0.innerHTML += ", DD]";
										} else if (pair.codec === "MPEG4/EAC3") {
											opt0.innerHTML += ", DD+]";
										} else if (pair.codec === "MPEG4/DTS") {
											opt0.innerHTML += ", DTS]";
										}
										if (stream0.proxied_url) {
											opt0.setAttribute("proxied_url", stream0.proxied_url);
										}
										if (stream0.isHDR) {
											opt0.innerHTML += " (HDR)";
										}
										videoCombined.appendChild(opt0);
									} catch (e) {
										console.error(e);
									}
								}
								for (var i = 0; i < jsonObject.videos.videoStreams.length; i++) {
									try {
										const stream1 = jsonObject.videos.videoStreams[i];
										const opt1 = document.createElement("option");
										opt1.setAttribute("dataType", "combinedSingle");
										opt1.setAttribute("url", stream1.proxied_url);
										opt1.setAttribute("proxied_url", stream1.proxied_url);
										opt1.setAttribute("listAttr", i);
										opt1.setAttribute("listAttr", "video");
										opt1.setAttribute("codec", stream1.pmime);
										opt1.innerHTML = stream1.quality + "p" + stream1.fps + "&nbsp;";
										if (stream1.codec === "MPEG4/H.264") {
											opt1.innerHTML += "[MP4]";
										} else if (stream1.codec === "MPEG4+WEBM/AV1") {
											opt1.innerHTML += "[AV1]";
										} else if (stream1.codec === "WEBM/VP8+9") {
											opt1.innerHTML += "[WebM]";
										}
										if (stream1.isHDR) {
											opt1.innerHTML += " (HDR)";
										}
										videoSeperate.appendChild(opt1);
									} catch (e) {
										console.error(e);
									}
								}
								for (var i = 0; i < jsonObject.videos.audioStreams.length; i++) {
									try {
										const stream2 = jsonObject.videos.audioStreams[i];
										const opt2 = document.createElement("option");
										opt2.setAttribute("dataType", "combinedSingle");
										opt2.setAttribute("url", stream2.proxied_url);
										opt2.setAttribute("proxied_url", stream2.proxied_url);
										opt2.setAttribute("listAttr", i);
										opt2.setAttribute("listAttr", "audio");
										opt2.setAttribute("codec", stream2.codec);
										if (stream2.codec === "MPEG4/AAC") {
											opt2.innerHTML = "AAC [" + stream2.format_bitrate + " kbps" + (stream2.surroundAudio ? ", SURR" : "") + "]";
										} else if (stream2.codec === "WEBM/VORBIS") {
											opt2.innerHTML = "Vorbis [" + stream2.format_bitrate + " kbps]";
										} else if (stream2.codec === "WEBM/OPUS") {
											opt2.innerHTML = "Opus [" + stream2.format_bitrate + " kbps]";
										} else if (stream2.codec === "MPEG3") {
											opt2.innerHTML = "MP3 [" + stream2.format_bitrate + " kbps]";
										} else if (stream2.codec === "MPEG4/AC3") {
											opt2.innerHTML = "DD [" + stream2.format_bitrate + " kbps" + (stream2.surroundAudio ? ", SURR" : "") + "]";
										} else if (stream2.codec === "MPEG4/EAC3") {
											opt2.innerHTML = "DD+ [" + stream2.format_bitrate + " kbps" + (stream2.surroundAudio ? ", SURR" : "") + "]";
										} else if (stream2.codec === "MPEG4/DTS") {
											opt2.innerHTML = "DTS [" + stream2.format_bitrate + " kbps" + (stream2.surroundAudio ? ", SURR" : "") + "]";
										}
										if (stream2["trackLang"]) {
											opt2.innerHTML += " (" + stream2["trackLang"] + ")";
										}
										if (stream2["isDRC"]) {
											opt2.innerHTML += " [DRC]";
										}
										audioSeperate.appendChild(opt2);
									} catch (e) {
										console.error(e);
									}
								}
								videoSelect.appendChild(combined);
								videoSelect.appendChild(videoCombined);
								videoSelect.appendChild(videoSeperate);
								videoSelect.appendChild(audioSeperate);
								var neededIndex = jsonObject.videos.combinedStreams.length + jsonObject.videos.preferred.video;
								if (isMobile || window.location.toString().contains("&no60")) {
									neededIndex = jsonObject.videos.preferred.comb;
								} else if (jsonObject.audioOnly == 1 || window.location.toString().contains("&audio")) {
									neededIndex = jsonObject.videos.combinedStreams.length + jsonObject.videos.audioStreams.length + jsonObject.videos.preferred.audio;
								}
								videoSelect.selectedIndex = neededIndex;
								try {
									id("_debug_current_codec").innerHTML = videoSelect.options[videoSelect.selectedIndex].getAttribute("codec");
								} catch (e) {
									console.error(e);
								}
								videoSelect.onchange = function () {
									try {
										var selected = videoSelect.options[videoSelect.selectedIndex];
										if (window._cancel_next_event) {
											window._cancel_next_event = false;
										}
										try {
											id("_debug_current_codec").innerHTML = selected.getAttribute("codec");
										} catch (e) {
											console.error(e);
										}
										if (selected.getAttribute("datatype") === "combinedPair") {
											if (selected.getAttribute("url") === null || selected.getAttribute("pairurl") === null) {
												console.error("Error changing video sources...");
												console.error(selected);
												return;
											}
											window.mainPlayer.applySource(selected.getAttribute("url"), selected.getAttribute("pair_proxied_url"));
										} else if (selected.getAttribute("datatype") === "combinedSingle") {
											if (selected.getAttribute("proxied_url") === null) {
												console.error("Error changing video sources...");
												console.error(selected);
												return;
											}
											window.mainPlayer.applySource(selected.getAttribute("proxied_url"), null);
										} else {
											console.log("Unknown type '" + selected.getAttribute("datatype") + "'.");
										}
									} catch (e) {
										alert("nTube: Failed to change source.\nYou may be opted into an experimental playback mode that doesn't support quality switching.\nCheck your browser's console for more info.");
										console.error(e);
									}
								};
							}
						});
						run_async(function () {
							const downloadSelect = id("ntube-dropdown-download-select");
							const downloadButton = id("ntube-dropdown-download-button");
							downloadSelect.innerHTML = "";
							const combined = document.createElement("optgroup"),
								videoSeperate = document.createElement("optgroup"),
								audioSeperate = document.createElement("optgroup");
							combined.label = "Fallback Streams";
							videoSeperate.label = "Video Streams";
							audioSeperate.label = "Audio Streams";
							for (var i = 0; i < jsonObject.videos.combinedStreams.length; i++) {
								try {
									const stream = jsonObject.videos.combinedStreams[i];
									const opt = document.createElement("option");
									opt.setAttribute("dataType", "combinedSingle");
									var real_url = stream.proxied_url;
									if (stream["size"] && stream["size"] > 0) {
										real_url += "&_fclen=" + stream["size"];
									}
									opt.setAttribute("url", real_url);
									opt.setAttribute("proxied_url", real_url);
									opt.setAttribute("listAttr", i);
									opt.setAttribute("listAttr", "comb");
									opt.setAttribute("codec", stream.mime);
									opt.innerHTML = stream.quality + "p" + stream.fps + "&nbsp;";
									if (stream.codec === "MPEG4/H.264") {
										opt.innerHTML += "[MP4]";
									} else if (stream.codec === "MPEG4+WEBM/AV1") {
										opt.innerHTML += "[AV1]";
									} else if (stream.codec === "WEBM/VP8+9") {
										opt.innerHTML += "[WebM]";
									} else if (stream.codec === "3GPP/MPEG4") {
										opt.innerHTML += "[3GPP]";
									}
									combined.appendChild(opt);
								} catch (e) {
									console.error(e);
								}
							}
							for (var i = 0; i < jsonObject.videos.videoStreams.length; i++) {
								try {
									const stream1 = jsonObject.videos.videoStreams[i];
									const opt1 = document.createElement("option");
									opt1.setAttribute("dataType", "combinedSingle");
									opt1.setAttribute("url", stream1.proxied_url);
									opt1.setAttribute("proxied_url", stream1.proxied_url);
									opt1.setAttribute("listAttr", i);
									opt1.setAttribute("listAttr", "video");
									opt1.setAttribute("codec", stream1.mime);
									opt1.innerHTML = stream1.quality + "p" + stream1.fps + "&nbsp;";
									if (stream1.codec === "MPEG4/H.264") {
										opt1.innerHTML += "[MP4]";
									} else if (stream1.codec === "MPEG4+WEBM/AV1") {
										opt1.innerHTML += "[AV1]";
									} else if (stream1.codec === "WEBM/VP8+9") {
										opt1.innerHTML += "[WebM]";
									}
									if (stream1.isHDR) {
										opt1.innerHTML += " (HDR)";
									}
									videoSeperate.appendChild(opt1);
								} catch (e) {
									console.error(e);
								}
							}
							for (var i = 0; i < jsonObject.videos.audioStreams.length; i++) {
								try {
									const stream2 = jsonObject.videos.audioStreams[i];
									const opt2 = document.createElement("option");
									opt2.setAttribute("dataType", "combinedSingle");
									opt2.setAttribute("url", stream2.proxied_url);
									opt2.setAttribute("proxied_url", stream2.proxied_url);
									opt2.setAttribute("listAttr", i);
									opt2.setAttribute("listAttr", "audio");
									opt2.setAttribute("codec", stream2.codec);
									if (stream2.codec === "MPEG4/AAC") {
										opt2.innerHTML = "AAC [" + stream2.format_bitrate + " kbps" + (stream2.surroundAudio ? ", SURR" : "") + "]";
									} else if (stream2.codec === "WEBM/VORBIS") {
										opt2.innerHTML = "Vorbis [" + stream2.format_bitrate + " kbps]";
									} else if (stream2.codec === "WEBM/OPUS") {
										opt2.innerHTML = "Opus [" + stream2.format_bitrate + " kbps]";
									} else if (stream2.codec === "MPEG3") {
										opt2.innerHTML = "MP3 [" + stream2.format_bitrate + " kbps]";
									} else if (stream2.codec === "MPEG4/AC3") {
										opt2.innerHTML = "DD [" + stream2.format_bitrate + " kbps" + (stream2.surroundAudio ? ", SURR" : "") + "]";
									} else if (stream2.codec === "MPEG4/EAC3") {
										opt2.innerHTML = "DD+ [" + stream2.format_bitrate + " kbps" + (stream2.surroundAudio ? ", SURR" : "") + "]";
									} else if (stream2.codec === "MPEG4/DTS") {
										opt2.innerHTML = "DTS [" + stream2.format_bitrate + " kbps" + (stream2.surroundAudio ? ", SURR" : "") + "]";
									}
									if (stream2["trackLang"]) {
										opt2.innerHTML += " (" + stream2["trackLang"] + ")";
									}
									if (stream2["isDRC"]) {
										opt2.innerHTML += " [DRC]";
									}
									audioSeperate.appendChild(opt2);
								} catch (e) {
									console.error(e);
								}
							}
							downloadSelect.appendChild(combined);
							downloadSelect.appendChild(videoSeperate);
							downloadSelect.appendChild(audioSeperate);
							if (jsonObject && jsonObject.metadata && jsonObject.metadata.playbackMode && true === false) {
								// TODO: Enable me in the future
								if (jsonObject.metadata.playbackMode === "yt_music") {
									const nmu = document.createElement("optgroup");
									nmu.label = "nMusic Downloader (alpha)";
									for (var i = 0; i < jsonObject.videos.audioStreams.length; i++) {
										try {
											const stream3 = jsonObject.videos.audioStreams[i];
											const opt3 = document.createElement("option");
											opt3.setAttribute("dataType", "combinedSingle");
											opt3.setAttribute("url", stream3.proxied_url);
											opt3.setAttribute("proxied_url", stream3.proxied_url);
											opt3.setAttribute("nmusic_single", "true");
											opt3.setAttribute("listAttr", i);
											opt3.setAttribute("listAttr", "audio");
											opt3.setAttribute("codec", stream3.codec);
											if (stream3.codec === "MPEG4/AAC") {
												opt3.innerHTML = "AAC [" + stream3.format_bitrate + " kbps" + (stream3.surroundAudio ? ", SURR" : "") + "]";
											} else if (stream3.codec === "WEBM/VORBIS") {
												opt3.innerHTML = "Vorbis [" + stream3.format_bitrate + " kbps]";
											} else if (stream3.codec === "WEBM/OPUS") {
												opt3.innerHTML = "Opus [" + stream3.format_bitrate + " kbps]";
											} else if (stream3.codec === "MPEG3") {
												opt3.innerHTML = "MP3 [" + stream3.format_bitrate + " kbps]";
											} else if (stream3.codec === "MPEG4/AC3") {
												opt3.innerHTML = "DD [" + stream3.format_bitrate + " kbps" + (stream3.surroundAudio ? ", SURR" : "") + "]";
											} else if (stream3.codec === "MPEG4/EAC3") {
												opt3.innerHTML = "DD+ [" + stream3.format_bitrate + " kbps" + (stream3.surroundAudio ? ", SURR" : "") + "]";
											} else if (stream3.codec === "MPEG4/DTS") {
												opt3.innerHTML = "DTS [" + stream3.format_bitrate + " kbps" + (stream3.surroundAudio ? ", SURR" : "") + "]";
											}
											nmu.appendChild(opt3);
										} catch (e) {
											console.error(e);
										}
									}
									downloadSelect.appendChild(nmu);
								}
							}
							downloadSelect.selectedIndex = 0;
							downloadButton.onclick = function () {
								try {
									var selected = downloadSelect.options[downloadSelect.selectedIndex];
									if (window._cancel_next_event) {
										window._cancel_next_event = false;
									}
									var _durl = selected.getAttribute("proxied_url");
									console.log("Downloading: " + _durl);
									window.open(_durl, "_blank");
								} catch (e) {
									console.error(e);
									alert("Failed to start download.\nCheck your browser's console for more info.");
								}
							};
						});
						run_async(function () {
							process_related(jsonObject);
						});
						run_async(function () {
							if (jsonObject.captions) {
								for (var i = 0; i < jsonObject.captions.length; i++) {
									var caption = jsonObject.captions[i];
									var track = document.createElement("track");
									track.kind = "captions";
									track.label = caption.text;
									track.srclang = caption.code;
									track.src = caption.url;
									mainPlayer.appendChild(track);
								}
							}
						});
						run_async(function () {
							if (jsonObject.metadata.comments) {
								const n = jsonObject.metadata.comments;
								id("_comments_initial_button").onclick = function () {
									loadComments(n, null, null);
								};
								show(id("_comments_initial_div"));
							}
						});
						run_async(function () {
							if (ENABLE_CASTING) {
								show(id("button-cast"));
								loadScripts(["https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1", "https://cdn.jsdelivr.net/gh/fenny/castjs@3.0.1/cast.min.js"], function () {
									if (!window.castDevice) window.castDevice = new Castjs();
									const castDevice = window.castDevice;
									id("button-cast").onclick = function () {
										if (castDevice.available) {
											const metadata = {
												title: jsonObject.metadata.title,
												description: "Provided via nTube.",
												poster: "https://i.ytimg.com/vi/" + VIDEO_ID + "/maxresdefault.jpg",
											};
											const source = jsonObject.videos.combinedStreams[jsonObject.videos.combinedStreams.length - 1].proxied_url;
											castDevice.cast(source, metadata);
										} else {
											alert("nTube Casting:\nThe selected device is unavailable.");
										}
									};
								});
							}
						});
						run_async(function () {
							if (jsonObject && jsonObject.metadata && jsonObject.metadata.playbackMode) {
								if (jsonObject.metadata.playbackMode === "yt_music" && !isMobile && !window.is_iPhoneOS()) {
									/* TODO(mainline): Port this over to a dynamic CSS rule set. */
									const info_div = id("-ntube-info-div");
									info_div.style.width = "calc(50% - 10px)";
									info_div.style.height = "100%";
									info_div.style.verticalAlign = "top";
									info_div.style.display = "inline-block";
									const vid_el = id("_primary_player");
									vid_el.style.width = "49vw";
									vid_el.style.height = "69vh";
									vid_el.style.position = "relative";
									vid_el.style.marginRight = "-5px";
									const vid_div = id("video_div");
									vid_div.style.width = "calc(50% - 5px)";
									vid_div.style.verticalAlign = "top";
									vid_div.style.display = "inline-block";
									hide(id("video_flags"));
									/* It really isn't worth showing the likes in YT Music mode... */
									hide(id("video_likes"));
									hide(id("video_rating_pre"));
								} else if (jsonObject.metadata.playbackMode === "yt_short") {
									try {
										displayMessage("nTube", "Entered shorts mode." + ".", 5000);
										id("_primary_player").style.maxHeight = "90vh";
									} catch (e) {
										console.error(e);
									}
								} else {
									// TODO: Implement other modes here.
								}
							}
						});
					}
				}
				if (ENABLE_CACHE && window.nTube.cache && window.nTube.cache.getItem(VIDEO_ID) !== null) {
					process_video(window.nTube.cache.getItem(VIDEO_ID));
				} else {
					request(
						url,
						JSON.stringify(jxr),
						function (exception) {
							console.error(exception);
							try {
								document.body.style.cursor = "";
							} catch (e) {}
							alert("nTube failed to talk with it's backend.\r\nCheck your browser's console for more information.\n" + exception);
						},
						function (data) {
							process_video(data);
						}
					);
				}
				try {
					document.body.style.cursor = "wait";
				} catch (e) {}
			};
			const NTUBE_USE_DCL = true;
			function __ntube_init_func() {
				run_async(function () {
					SearchBar.init();
					id("_search_results").innerHTML = "";
				});
				run_async(function () {
					id("cinema_mode_toggle_overlay").onclick = function () {
						cinema_mode_toggle();
					};
				});
				run_task(window.__init, libWeb.TaskDispatcher.TaskPriority.BLOCKING_TASK);
				if (getQueryVariable("redirect") !== null) {
					var rdr = getQueryVariable("redirect");
					if (rdr === "from_script_popup") {
						displayMessage("nTubeifier", "You've been redirected from YouTube.", 5000);
					} else if (rdr === "from_search_query") {
						displayMessage("nTubeifier", "This is a URL, sent you to the video instead.", 5000);
						if (nTube.nTubeUtils.getRandomInt(0, 10) > 9) {
							displayMessage("nTubeifier", "You know you could've pasted it into the URL bar?", 5000);
						}
					}
				}
			}
			if (NTUBE_USE_DCL) {
				window.addEventListener("DOMContentLoaded", function (event) {
					__ntube_init_func();
				});
			} else {
				window.onload = __ntube_init_func;
			}
		</script>
	</head>

	<body style="background-size: auto; background-repeat: repeat">
		<div class="menu">
			<div class="menu-item">
				<p style="padding-left: 5px; margin-top: 5px; vertical-align: middle; font-weight: bold; display: inline-block; margin-right: 15px; width: auto">
					<span style="color: red">n</span><span id="ntube_main_menu_tube_label" style="color: lightgreen">Tube</span>
					<sub id="ntube_version_main_menu_label" style="font-size: 0.9em; line-height: 25%">1.5.0</sub>
					<img id="ntube-winter-logo" src="resources/events/christmas.png" title="Merry Christmas!" decoding="async" loading="lazy" />
				</p>
				<div style="display: inline-block; vertical-align: middle; margin-right: 5px">
					<a href="/" title="Home Page">
						<img src="resources/icons/home.svg" alt="home" style="height: 2em; width: 2em" decoding="async" loading="lazy" />
					</a>
				</div>
				<div style="display: inline-block; vertical-align: middle; margin-right: 5px">
					<a href="/trending" title="Trending Videos">
						<img src="resources/icons/trending.svg" alt="trending" style="height: 2em; width: 2em" decoding="async" loading="lazy" />
					</a>
				</div>
				<div style="display: inline-block; vertical-align: middle; margin-right: 5px; margin-bottom: 3px">
					<a href="/settings" title="Settings">
						<img src="resources/icons/settings.svg" alt="settings" style="height: 2em; width: 2em" decoding="async" loading="lazy" />
					</a>
				</div>
			</div>
			<div class="menu-item">
				<div class="flex_box_compat" style="height: 100%">
					<style>
						#search_overlay {
							z-index: 8;
							position: fixed;
							background-color: rgba(0, 0, 0, 0.95);
							width: 100%;
							height: 100%;
							top: 0px;
							left: 0px;
						}

						.search_hidden {
							display: none;
							visibility: hidden;
						}

						#search_bar {
							background-color: inherit;
							color: inherit;
							border: none;
							border-left: 1px solid green;
							height: 100%;
							transition: border-bottom 0.5s ease-in-out;
							font-family: monospace;
							font-size: large;
							text-indent: 5px;
							flex-grow: 1;
							min-width: 50%;
						}

						#search_bar:focus {
							border-bottom: 1px solid green;
						}

						#search_button {
							border: none;
							border-left: 1px solid rgba(0, 128, 0, 0.7);
							border-right: none;
							height: 100%;
							background-color: inherit;
							color: inherit;
							margin-right: 0px;
							font-family: inherit;
						}
					</style>
					<input id="search_bar" type="text" name="Search nTube Bar." placeholder="Search nTube." />
					<button id="search_button" onclick="search_start(null);">Search</button>
				</div>
			</div>
		</div>
		<div id="search_overlay" class="search_hidden">
			<div style="padding-bottom: 30px"></div>
			<!--search_hidden-->
			<div id="search-top-ui" style="width: 100%; color: inherit">
				<div style="float: left; padding-left: 5px">
					<h1 style="margin-top: 5px; margin-bottom: 5px">Search.</h1>
					<h3 style="margin-top: 5px; margin-bottom: 10px">Searching for <span id="search_query_display_string">uhhh...nothing.</span>.</h3>
				</div>
				<div style="float: right; padding-right: 15px; padding-top: 15px">
					<button style="width: 100px; height: 50px; border-radius: 30px; border: 1px solid green; background-color: inherit; color: inherit; font-family: inherit" onclick="search_close()">Close.</button>
					<script defer="defer">
						function search_close() {
							id("search_overlay").classList.add("search_hidden");
						}
					</script>
				</div>
				<div style="clear: both"></div>
			</div>
			<div id="_search_results" class="poly-item" style="width: calc(100% - 30px); height: 78%; margin-right: 0px; overflow-y: auto; color: inherit; margin-left: 5px">
				<div class="search-item">
					<a class="search-link" href="#gotoShittyVideo">
						<img src="" alt="TOTALLY NOT CLICKBAIT" style="padding-left: 5px; display: inline; vertical-align: middle; width: 220px; height: 160px; margin-bottom: 5px" decoding="async" />
						<div style="padding-left: 15px; display: inline; vertical-align: middle">
							<p style="position: absolute; display: inline; vertical-align: middle; font-size: large; margin-top: 15px">CLICKBAIT TITLE</p>
							<p style="position: absolute; display: inline; vertical-align: bottom; font-size: small; margin-top: 45px">00:00 &centerdot; -1 &centerdot; <a href="#gotoShittyChannel">CHANNEL #2492049</a></p>
						</div>
					</a>
				</div>
			</div>
			<center>
				<button id="_search_load_more">Load more.</button>
			</center>
		</div>
		<div
			id="cinema_mode_toggle_overlay"
			style="
				display: none;
				visibility: hidden;
				position: fixed;
				top: 0px;
				left: 5px;
				width: 32px;
				height: 28px;
				margin-top: -5px;
				z-index: 17;
				background-color: rgba(0, 0, 0, 0.4);
				border: 1px solid rgb(87, 111, 230);
				border-top: none;
			"
		>
			<img style="width: 32px; height: 32px; transform: rotate(180deg)" src="resources/icons/full_window.svg" alt="Collapse." decoding="async" />
		</div>
		<div id="commander_overlay" class="commander_overlay" style="display: none; visibility: hidden">
			<div id="commander_main_div" class="commander_mdiv">
				<input id="commander_text_input" class="commander_text_box" type="text" value="" placeholder="nTube Commander." />
				<p class="commander_text_out" id="commnader_text_output" style="display: none; visibility: hidden">Ready.</p>
			</div>
		</div>
		<style>
			#playback_error_overlay {
				z-index: 7;
				position: fixed;
				top: 40%;
				left: 50%;
				transform: translate(-50%, -50%);
				padding-bottom: 5px;
				padding-right: 5px;
				color: white !important;
				background-color: rgba(20, 20, 20, 0.9) !important;
				width: 50vw;
				height: fit-content;
			}
		</style>
		<div id="playback_error_overlay" style="display: none; visibility: hidden">
			<div class="poly-item" style="border: 1px solid rgba(164, 121, 0, 0.9) !important; box-shadow: none !important; margin-bottom: -5px !important; margin-right: -5px !important">
				<h1 style="margin-top: 5px; margin-bottom: 10px">Playback error.</h1>
				<div>
					nTube's playback engine has signalled an unrecoverable error and cannot continue.
					<br />
					Sorry about that.
					<br />
					<br />
					(p.s. reloading the page might help.)
					<br />
					<br />
					Information for developers:
					<br />
					<pre id="playback_error_info" style="height: 64px; margin-bottom: 5px; white-space: initial; word-wrap: anywhere; overflow-y: scroll">
					Generating...
					</pre
					>
					<button id="playback_error_dismiss_button" class="flat-button" style="color: inherit; margin-bottom: 5px; width: calc(100% - 5px)">Dismiss error.</button>
				</div>
			</div>
		</div>
		<div style="padding-bottom: 30px"></div>
		<noscript>
			<div class="poly-item" style="border: 1px solid orangered">
				<h2 style="margin-top: 5px; margin-bottom: 5px">JavaScript required.</h2>
				<p style="margin-top: 5px; margin-bottom: 5px">This page requires JavaScript in order to run. Please enable it or use the fallback pages.</p>
			</div>
		</noscript>
		<script async="async">
			function __generate_playback_error(more_info) {
				id("playback_error_info").innerHTML = more_info;
				show(id("playback_error_overlay"));
			}
			id("playback_error_dismiss_button").onclick = function () {
				hide(id("playback_error_overlay"));
			};
		</script>
		<div id="filter-warning-div" class="poly-item" style="border: 1px solid orange; display: none; visibility: hidden">
			<h3>Filter triggered.</h3>
			<p>
				This video triggers a selected nTube (or custom) filter. Are you sure you want to continue? <br />
				Video Title: <span>%video_title</span>
			</p>
			<center>
				<button title="Play video despite filter.">Continue.</button>
			</center>
		</div>
		<div id="browser-console-debug" style="position: absolute; top: 0px; left: 0px; z-index: 20; display: none; visibility: hidden">
			<div id="browser-console-debug-items"></div>
			<script async="async">
				if (!window.getQueryVariable) {
					window.getQueryVariable = function (variable) {
						var query = window.location.search.substring(1);
						var vars = query.split("&");
						for (var i = 0; i < vars.length; i++) {
							var pair = vars[i].split("=");
							if (decodeURIComponent(pair[0]) == variable) {
								return decodeURIComponent(pair[1]);
							}
						}
						return null;
					};
				}
				if (window.getQueryVariable("debugging") !== null) {
					window.console.log = function (x) {
						const i = id("browser-console-debug-items");
						var o = document.createElement("div");
						o.innerHTML = x;
						o.style.backgroundColor = "rgba(0, 0, 0, 0.8)";
						o.style.fontFamily = "monospace";
						i.appendChild(o);
					};
					window.console.info = function (x) {
						const i = id("browser-console-debug-items");
						var o = document.createElement("div");
						o.innerHTML = x;
						o.style.backgroundColor = "rgba(0, 0, 0, 0.8)";
						o.style.fontFamily = "monospace";
						i.appendChild(o);
					};
					window.console.error = function (x) {
						const i = id("browser-console-debug-items");
						var o = document.createElement("div");
						o.innerHTML = x;
						o.style.backgroundColor = "rgba(0, 0, 0, 0.8)";
						o.style.color = "red";
						o.style.fontFamily = "monospace";
						i.appendChild(o);
					};
					window.console.warn = function (x) {
						const i = id("browser-console-debug-items");
						var o = document.createElement("div");
						o.innerHTML = x;
						o.style.backgroundColor = "rgba(0, 0, 0, 0.8)";
						o.style.color = "orange";
						o.style.fontFamily = "monospace";
						i.appendChild(o);
					};
					window.console.debug = function (x) {
						const i = id("browser-console-debug-items");
						var o = document.createElement("div");
						o.innerHTML = x;
						o.style.backgroundColor = "rgba(0, 0, 0, 0.8)";
						o.style.color = "gray";
						o.style.fontFamily = "monospace";
						i.appendChild(o);
					};
					id("browser-console-debug").style.display = "";
					id("browser-console-debug").style.visibility = "";
				}
			</script>
		</div>
		<div class="not-a-overlay" id="message-overlay" style="background: none; bottom: 10%; right: 0px; padding: 5px">
			<!--<p id="video-message"></p> display: none; visibility: hidden;-->
		</div>
		<style>
			#share_overlay {
				z-index: 7;
				position: fixed;
				top: 40%;
				left: 50%;
				transform: translate(-50%, -50%);
				padding-bottom: 5px;
				padding-right: 5px;
				color: white !important;
				background-color: rgba(20, 20, 20, 0.9) !important;
				width: 40vw;
				height: fit-content;
			}

			.ntube_logo_text_red {
				color: red;
				vertical-align: middle;
			}

			.ntube_logo_text_green {
				color: lightgreen;
				vertical-align: middle;
			}

			.ntube_share_small_margin {
				margin-top: 5px;
				margin-bottom: 5px;
			}

			.ntube_share_no_margin {
				margin-top: 0px;
				margin-bottom: 0px;
			}

			.share_ui_types {
				display: flex;
				align-items: center;
				justify-content: center;
			}

			.share_ui_type {
				display: flex;
				-moz-flex-direction: column;
				-webkit-flex-direction: column;
				-webkit-box-flex-direction: column;
				-ms-flex-direction: column;
				flex-direction: column;
				padding: 5px;
				margin-right: 5px;
			}

			.ntube_share_type_name {
				text-align: center;
			}

			.ntube_yt_logo_clone {
				color: white;
				background-color: red;
				border-radius: 5px;
				margin-left: 13px;
				margin-right: 13px;
			}

			.share_overlay_out_text {
				background-color: inherit;
				color: inherit;
				font-family: inherit;
				font-size: large;
				border: none;
				border-bottom: 1px solid lightgreen;
				width: 75%;
			}

			.share_overlay_out_text:focus {
				border-bottom: 1px solid aqua;
				outline: none;
			}

			.share_dismiss_btn {
				background-color: inherit;
				color: inherit;
				font-family: inherit;
				font-size: medium;
				border: 1px solid green;
			}

			.share_dismiss_btn:active {
				border: 1px solid aqua;
			}
		</style>
		<div id="share_overlay" class="poly-item" style="display: none; visibility: hidden">
			<h2 style="margin-top: 5px; margin-bottom: 5px">Share.</h2>
			<center id="share_overlay_format_selector">
				<p class="ntube_share_small_margin" style="margin-bottom: 20px">Select a URL format.</p>
				<div class="share_ui_types">
					<div id="share_overlay_btn_for_ntube" class="poly-item share_ui_type">
						<h3 class="ntube_share_no_margin"><span class="ntube_logo_text_red">n</span><span class="ntube_logo_text_green">T</span></h3>
						<p class="ntube_share_no_margin ntube_share_type_name">nTube.</p>
					</div>
					<div id="share_overlay_btn_for_yt" class="poly-item share_ui_type">
						<h3 class="ntube_share_no_margin ntube_yt_logo_clone">&#9658;</h3>
						<p class="ntube_share_no_margin ntube_share_type_name">YouTube.</p>
					</div>
				</div>
				<input type="checkbox" id="share_menu_include_playlist_meta" name="share_menu_include_playlist_meta" value="" style="display: inline-block !important" />
				<label for="share_menu_include_playlist_meta">Include Playlist Information (YouTube Only)</label><br />
			</center>
			<center id="share_overlay_output" style="display: none; visibility: hidden">
				<h3 class="ntube_share_small_margin" style="margin-bottom: 5px">Sharing URL.</h3>
				<input id="share_overlay_url_input" class="share_overlay_out_text" type="text" editable="false" value="https://example.com/" />
				<p class="ntube_share_small_margin" style="margin-bottom: 10px">Click the input box to copy to clipboard.</p>
				<button id="share_overlay_out_dismiss" class="share_dismiss_btn">Dismiss.</button>
			</center>
		</div>
		<script defer="defer">
			id("share_overlay_out_dismiss").onclick = function () {
				hide(id("share_overlay_output"));
				hide(id("share_overlay"));
				show(id("share_overlay_format_selector"));
			};
			id("share_overlay_url_input").onclick = function () {
				try {
					var x = copyToClipboard(id("share_overlay_url_input").value);
					if (x instanceof Promise || x === true) {
						// Assume no explosions
						displayMessage("Share.", "Copied to clipboard.", 2000);
					} else {
						displayMessage("Share.", "Failed to copy to clipboard.", 3000);
					}
				} catch (e) {
					console.error(e);
				}
			};
			id("share_overlay_btn_for_ntube").onclick = function () {
				id("share_overlay_url_input").value = window.location.toString();
				show(id("share_overlay_output"));
				hide(id("share_overlay_format_selector"));
			};
			id("share_overlay_btn_for_yt").onclick = function () {
				const videoID = getQueryVariable("v");
				id("share_overlay_url_input").value = "https://www.youtube.com/watch?v=" + videoID;
				if (id("share_menu_include_playlist_meta").checked) {
					var playlistId = getQueryVariable("list");
					var playlistIdx = getQueryVariable("index");
					if (playlistId !== null) {
						id("share_overlay_url_input").value += "&list=" + playlistId;
					}
					if (playlistIdx !== null) {
						id("share_overlay_url_input").value += "&index=" + playlistIdx;
					}
				}
				show(id("share_overlay_output"));
				hide(id("share_overlay_format_selector"));
			};
		</script>
		<script defer="defer">
			function displayMessage() {
				// title, message, duration
				const args = arguments;
				if (args === null || args.length < 0) throw new Error("Invalid arguments!");
				var title = "nTube";
				var message = null;
				var duration = 5000;
				if (args.length === 1) {
					const arg = args[0];
					if (typeof arg === "string") {
						message = arg;
					} else {
						throw new Error("Unsupported value: " + arg);
					}
				} else if (args.length === 2) {
					for (var i = 0; i < args.length; i++) {
						const arg1 = args[i];
						if (typeof arg1 === "string") {
							message = arg1;
						} else if (typeof arg1 === "number") {
							duration = arg1;
						} else {
							throw new Error("Unsupported value: " + arg1);
						}
					}
				} else if (args.length === 3) {
					for (var i = 0; i < args.length; i++) {
						const arg2 = args[i];
						if (typeof arg2 === "string") {
							if (i == 0) {
								title = arg2;
							} else {
								message = arg2;
							}
						} else if (typeof arg2 === "number") {
							duration = arg2;
						} else {
							throw new Error("Unsupported value: " + arg2);
						}
					}
				} else {
					throw new Error("Unsupported argument count!");
				}
				var msgo = id("message-overlay");
				var mdiv = document.createElement("div");
				mdiv.classList.add("message_div");
				var pdiv = document.createElement("div");
				pdiv.style.paddingTop = "5px";
				mdiv.appendChild(pdiv);
				var tspan = document.createElement("span");
				tspan.classList.add("message_title");
				tspan.innerHTML = title;
				mdiv.appendChild(tspan);
				mdiv.appendChild(document.createElement("br"));
				mdiv.innerHTML += message;
				msgo.appendChild(mdiv);
				setTimeout(function () {
					msgo.removeChild(mdiv);
				}, duration);
			}
		</script>
		<div class="poly-item" style="height: 85%; padding-left: 0px; contain-intrinsic-height: 70vw" id="video_div">
			<style>
				.fruit_style_overlay {
					z-index: 5;
					position: absolute;
					font-family: inherit;
					pointer-events: none;
				}

				.fruit_text {
					font-family: inherit;
				}

				.nplayer_ui_core_overlay {
					z-index: 1;
					position: fixed;
					top: 0px;
					left: 0px;
					width: 100%;
					height: 100%;
					background-color: rgba(152, 250, 87, 0.2);
					pointer-events: none;
				}

				.nplayer_ui_player_overlay {
					z-index: 1;
					position: fixed;
					bottom: 0%;
					width: 100%;
					height: 15%;
					background-color: rgba(217, 255, 0, 0.2);
				}

				.nplayer_ui_player_el {
					-moz-flex-wrap: wrap;
					-webkit-flex-wrap: wrap;
					-webkit-box-flex-wrap: wrap;
					-ms-flex-wrap: wrap;
					flex-wrap: wrap;
					margin: 5px;
					vertical-align: middle;
					align-items: center;
				}

				.nplayer_ui_player_buttons {
					display: flex;
					margin-top: -5px;
				}

				@-moz-document url-prefix() {
					.nplayer_ui_player_overlay {
						bottom: 10%;
					}
				}

				.nplayer_ui_player {
					background-color: rgba(62, 62, 62, 0.441);
					width: 98%;
					height: 70%;
					margin: 0 auto;
					margin-top: 10px;
					margin-bottom: 10px;
					border: 1px solid rgba(0, 0, 0, 0.8);
					padding: 1px;
					box-shadow: 0 10px 10px rgba(255, 255, 255, 0.08), 0 10px 10px rgba(255, 255, 255, 0.08);
					pointer-events: all;
					display: grid;
				}

				.nplayer_overlay {
					z-index: 1;
					position: relative;
					left: 0;
					bottom: 5px;
					margin: 0 auto;
				}

				.nplayer-internal {
					position: absolute;
				}

				.nplayer_button {
					border: none;
					background-color: transparent;
				}

				.nplayer_ui_player_play_button {
					font-weight: bolder;
					font-size: x-large;
					padding-left: 10px;
					padding-right: 10px;
				}

				.nplayer_ui_player_seek {
					margin-right: 10px;
				}

				.message_div {
					background: rgba(0, 0, 0, 0.9);
					border: 1px solid green;
					width: auto;
					padding-left: 5px;
					padding-right: 5px;
					padding-bottom: 5px;
				}

				.message_title {
					font-weight: bold;
					line-height: 80%;
					font-size: large;
				}
			</style>
			<div class="fruit_style_overlay" style="width: calc(100% - 17px); height: 55vw; overflow: hidden; display: none; visibility: hidden" id="fruit_loader">
				<div style="z-index: 4; width: 100%; height: 100%; filter: blur(5px); position: absolute; background-color: rgba(0, 0, 0, 0.4)"></div>
				<div style="z-index: 5; position: absolute">
					<h1 class="fruit_text" style="line-height: 5px; margin-left: 5px; text-shadow: -1.5px -1.5px 0 #000, 1.5px -1.5px 0 #000, -1.5px 1.5px 0 #000, 1.5px 1.5px 0 #000; color: white">Loading...</h1>
				</div>
			</div>
			<div class="nplayer_ui_core_overlay" nplayer-type="LAYER_CORE_OVERLAY" style="display: none; visibility: hidden">
				LAYER_CORE_OVERLAY
				<div class="nplayer_ui_player_overlay" nplayer-type="LAYER_PLAYER_OVERLAY">
					<div class="nplayer_ui_player">
						<div class="nplayer_ui_player_el nplayer_ui_player_seek">
							<div class="seekbar">
								<input type="range" value="0.0" style="width: 100%" />
								<div class="seekbar-progress">
									<div role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" style="width: 100%"></div>
								</div>
							</div>
						</div>
						<div class="nplayer_ui_player_el nplayer_ui_player_buttons">
							<div class="nplayer_ui_player_el nplayer_button nplayer_ui_player_play_button">&#9654;</div>
							<!-- VOLUME -->
							<span class="nplayer_ui_player_el nplayer_ui_player_time_label">00:00</span>
							<span class="nplayer_ui_player_el">/</span>
							<span class="nplayer_ui_player_el nplayer_Ui_player_time_total_label">00:00</span>
						</div>
					</div>
				</div>
			</div>
			<div id="video_primary_div">
				<!--Used for 360 video support to override the element for a canvas.-->
				<center id="actual-primary-video-div">
					<div id="-360-video-div" style="display: none; visibility: hidden; width: 100%; height: 90vh; touch-action: none; -moz-user-select: none"></div>
					<canvas id="_primary_canvas" style="display: none; visibility: hidden; padding-left: 0px"></canvas>
					<video id="_primary_player" data-dashjs-player style="height: auto; background-size: cover; width: 100%; max-height: 90vh; image-rendering: auto; display: block" playsinline="true" preload="auto" autoplay></video>
				</center>
			</div>
			<script defer="defer">
				function __nt_init_commentsUI(url, so) {
					var actl = id("actual-primary-video-div");
					id("_primary_player").style.float = "left";
					id("_primary_player").style.width = "70%";
					id("_primary_player").style.height = "38vw";
					var cl = document.createElement("div");
					var wd = document.createElement("div");
					wd.style.textAlign = "center";
					wd.id = "--chat-div";
					wd.innerHTML = '<h1>Warning!</h1><p style="color: orange;">Enabling live chat will make nTube connect to YouTube\'s services.</p>';
					var sb = document.createElement("button");
					sb.style.color = "inherit";
					sb.style.backgroundColor = "inherit";
					sb.style.fontFamily = "inherit";
					sb.style.border = "1px solid green";
					sb.style.padding = "5px";
					sb.innerHTML = "Connect anyways.";
					wd.appendChild(sb);
					var db = document.createElement("p");
					db.style.fontFamily = "inherit";
					db.innerHTML = "Close chat.";
					db.style.textDecoration = "underline dotted gray";
					db.onclick = function () {
						sb.disabled = true;
						wd.style.display = "none";
						wd.style.visibility = "hidden";
						ifr.style.display = "none";
						ifr.style.visibility = "hidden";
						id("_primary_player").style.float = "";
						id("_primary_player").style.width = "100%";
						id("_primary_player").style.height = "100%";
						actl.removeChild(m0);
						actl.removeChild(cl);
					};
					wd.appendChild(db);
					var m0 = document.createElement("div");
					m0.classList.add("ntube-livestream-chat-div");
					m0.style.float = "right";
					m0.style.width = "30%";
					m0.style.height = "38vw";
					var ifr = document.createElement("iframe");
					ifr.setAttribute("frameborder", "0");
					isolateFrame(ifr);
					ifr.loading = "lazy";
					ifr.style.width = "100%";
					ifr.style.height = "100%";
					ifr.style.backgroundColor = "#222";
					ifr.style.display = "none";
					ifr.style.visibility = "hidden";
					sb.onclick = function () {
						sb.disabled = true;
						wd.style.display = "none";
						wd.style.visibility = "hidden";
						ifr.style.display = "";
						ifr.style.visibility = "";
						ifr.src = url;
					};
					if (so && so.appearance && so.appearance.yt_chat_enforce_dark_mode) {
						ifr.style.filter = "invert(1)";
					}
					if (so && so.privacy && so.privacy.yt_auto_enable_live_chat) {
						ifr.style.display = "";
						ifr.style.visibility = "";
						ifr.src = url;
					} else {
						m0.appendChild(wd);
					}
					m0.appendChild(ifr);
					cl.style.clear = "both";
					actl.appendChild(m0);
					actl.appendChild(cl);
					return ifr;
				}
			</script>
			<style>
				#debug_overlay {
					z-index: 7;
					position: absolute;
					top: 0px;
					padding-bottom: 5px;
					padding-right: 5px;
					color: white;
				}

				.debug-text {
					font-family: inherit;
					font-size: small;
					margin-top: 1px;
					margin-bottom: 1px;
					-webkit-text-stroke: 0.3px black;
					text-stroke: 0.3px black;
					font-weight: bold;
				}

				.toggle:checked + .lbl-toggle + .collapsible-content {
					backdrop-filter: blur(6px);
					-webkit-backdrop-filter: blur(6px);
				}

				.collapsible-content .content-inner {
					background: rgb(18 17 26 / 0.6);
				}
			</style>
			<div id="debug_overlay" style="display: none; visibility: hidden">
				<div style="padding-left: 5px">
					<div>
						<p style="font-family: inherit; margin-top: 2px; margin-bottom: 2px; float: left; font-weight: bolder; -webkit-text-stroke: 0.4px black; text-stroke: 0.4px black">nTube Debugging v1.2</p>
						<div style="clear: both"></div>
					</div>
					<div class="wrap-collabsible" style="width: 400px">
						<input id="debug_basic_tab" class="toggle" type="checkbox" />
						<label for="debug_basic_tab" class="lbl-toggle">Basics.</label>
						<div class="collapsible-content">
							<div class="content-inner">
								<div>
									<p class="debug-text" style="float: left">nTube Version:</p>
									<p id="__debug_overlay_ntv" class="debug-text" style="float: right">N/A</p>
									<div style="clear: both"></div>
								</div>
								<div>
									<p class="debug-text" style="float: left">Video ID:</p>
									<p id="__debug_overlay_video_id" class="debug-text" style="float: right">N/A</p>
									<div style="clear: both"></div>
								</div>
							</div>
						</div>
					</div>
					<div class="wrap-collabsible" style="width: 400px">
						<input id="debug_players_tab" class="toggle" type="checkbox" />
						<label for="debug_players_tab" class="lbl-toggle">Players.</label>
						<div class="collapsible-content">
							<div class="content-inner">
								<div>
									<p class="debug-text" style="float: left">nPlayerNX Version:</p>
									<p id="__debug_overlay_nplayernx_ver" class="debug-text" style="float: right">N/A</p>
									<div style="clear: both"></div>
								</div>
								<div>
									<p class="debug-text" style="float: left">nMuxer Version:</p>
									<p id="__debug_overlay_nmuxer_ver" class="debug-text" style="float: right">N/A</p>
									<div style="clear: both"></div>
								</div>
								<div>
									<p class="debug-text" style="float: left">dash.js Version:</p>
									<p id="__debug_overlay_dash_ver" class="debug-text" style="float: right">N/A</p>
									<div style="clear: both"></div>
								</div>
								<div>
									<p class="debug-text" style="float: left">rxPlayer Version:</p>
									<p id="__debug_overlay_rxplayer" class="debug-text" style="float: right">N/A</p>
									<div style="clear: both"></div>
								</div>
								<div>
									<p class="debug-text" style="float: left">Redwood Version:</p>
									<p id="__debug_overlay_redwood_ver" class="debug-text" style="float: right">N/A</p>
									<div style="clear: both"></div>
								</div>
							</div>
						</div>
					</div>
					<div class="wrap-collabsible" style="width: 400px">
						<input id="media_players_tab" class="toggle" type="checkbox" />
						<label for="media_players_tab" class="lbl-toggle">Media.</label>
						<div class="collapsible-content">
							<div class="content-inner">
								<div>
									<p class="debug-text" style="float: left">Playback Information:</p>
									<p class="debug-text" style="float: right">
										<span id="_debug_vpd_0" title="Total Frames">0</span>/<span id="_debug_vpd_1" title="Dropped Frames">0</span>/<span id="_debug_vpd_2" title="Corrupted Frames">0</span>
									</p>
									<div style="clear: both"></div>
								</div>
								<div>
									<p class="debug-text" style="float: left">Codecs:</p>
									<p class="debug-text" style="float: right">(quality: <span id="_debug_quality">N/A</span>p) <span id="_debug_current_codec">N/A</span></p>
									<div style="clear: both"></div>
								</div>
								<div>
									<p class="debug-text" style="float: left">Sync:</p>
									<p id="__debug_sync_method" class="debug-text" style="float: right">N/A</p>
									<div style="clear: both"></div>
								</div>
								<div>
									<p class="debug-text" style="float: left">Data Saving</p>
									<p id="__data_saving_status" class="debug-text" style="float: right">Inactive.</p>
									<div style="clear: both"></div>
								</div>
							</div>
						</div>
					</div>
					<div class="wrap-collabsible" style="width: 400px">
						<input id="buffer_player_tab" class="toggle" type="checkbox" />
						<label for="buffer_player_tab" class="lbl-toggle">Buffers.</label>
						<div class="collapsible-content">
							<div class="content-inner">
								<p class="debug-text">Video Buffer:</p>
								<div id="__debug_overlay_buffer_canvas_back" style="vertical-align: middle; display: inline-block; background-color: gray; line-height: 30%; width: 320px">
									<div id="__debug_overlay_canvas" style="width: 0px; background-color: green; font-size: 0px">&nbsp;</div>
								</div>
								<span class="debug-text" id="__debug_canvas_time" style="vertical-align: middle; background-color: transparent; display: inline-block; margin-right: -10px">0.00s</span>
								<div id="--debug-overlay-bitrate" style="display: none; visibility: hidden">
									<p class="debug-text">Bitrate Usage:</p>
									<div id="__debug_br_overlay_buffer_canvas_back" style="vertical-align: middle; display: inline-block; background-color: gray; line-height: 30%; width: 320px">
										<div id="__debug_br_overlay_canvas" style="width: 0px; background-color: green; font-size: 0px">&nbsp;</div>
									</div>
									<span class="debug-text" id="__debug_br_canvas" style="vertical-align: middle; background-color: transparent; display: inline-block; margin-right: -10px">0%</span>
								</div>
							</div>
						</div>
					</div>
				</div>
				<script defer="defer">
					function getMaxBufferSize() {
						if (isMobile || is_iPhoneOS()) {
							return 30;
						} else if (navigator.userAgent.contains("CrKey")) {
							return 45;
						} else {
							return 120;
						}
					}
					function __debugging_start() {
						show(id("debug_overlay"));
						var pp = id("_primary_player");
						var sm = window.nTubeVideo ? nTubeVideo.syncMethod : undefined;
						if (pp == null || sm === "redwood") {
							try {
								pp = document.getElementsByClassName("video-stream html5-main-video")[0];
							} catch (e) {}
						}
						if (pp.tagName === "DIV") {
							pp = pp.children[0];
						}
						id("__debug_overlay_ntv").innerHTML = nTube.version;
						var supportsBitrateUsage = false;
						if (window.dashjs) {
							id("__debug_overlay_dash_ver").innerHTML = dashjs.Version;
							show(id("--debug-overlay-bitrate"));
							supportsBitrateUsage = true;
						}
						if (window.nPlayerNX) {
							id("__debug_overlay_nplayernx_ver").innerHTML = nPlayerNX.versionString;
						}
						if (window.nMuxer) {
							id("__debug_overlay_nmuxer_ver").innerHTML = nMuxer.version;
						}
						if (window.RxPlayer && window.RxPlayer.version) {
							id("__debug_overlay_rxplayer").innerHTML = RxPlayer.version;
						}
						if (window.Redwood) {
							id("__debug_overlay_redwood_ver").innerHTML = Redwood.version;
						}
						if (window.Config.extraction.dataSaving) {
							if (window.Config.extraction.dataSaving === "on" || isDataSaver()) {
								id("__data_saving_status").innerHTML = "Active.";
							}
						}
						var bufferSize = getMaxBufferSize();
						window.__debugging_interval = setInterval(function () {
							run_promise(function () {
								try {
									try {
										id("_debug_quality").innerHTML = pp.videoHeight.toString();
									} catch (f1) {
										id("_debug_quality").innerHTML = "" + pp.videoHeight;
									}
								} catch (e) {
									console.error(e);
								}
							});
							run_promise(function () {
								try {
									if (window.ndashPlayer) {
										function substringBetween(s, a, b) {
											var p = s.indexOf(a) + a.length;
											return s.substring(p, s.indexOf(b, p));
										}
										var str = "";
										try {
											const t_dash = ndashPlayer.getCurrentTrackFor("video");
											str += substringBetween(t_dash.codec, '"', '"');
										} catch (e) {
											console.error(e);
										}
										try {
											const t1_dash = ndashPlayer.getCurrentTrackFor("audio");
											str += ", " + substringBetween(t1_dash.codec, '"', '"');
										} catch (e) {
											console.error(e);
										}
										id("_debug_current_codec").innerHTML = str;
									} else if (window.playerInstance && window.RxPlayer) {
										try {
											const rx_player_representations = Object.values(playerInstance._priv_contentInfos.activeRepresentations);
											const rx_player_active_representation = rx_player_representations[0];
											if (rx_player_active_representation === undefined) {
												return;
											}

											var str = "";
											const video = rx_player_active_representation.video;
											const audio = rx_player_active_representation.audio;
											if (video !== null && video !== undefined) {
												if (video.codec) {
													str += video.codec + ", ";
												} else {
													str += video.codecs.join(", ") + ", ";
												}
											}
											if (audio !== null && audio !== undefined) {
												if (audio.codec) {
													str += audio.codec;
												} else {
													str += audio.codecs.join(", ");
												}
											}
											id("_debug_current_codec").innerHTML = str;
										} catch (e) {
											console.error(e);
										}
									} else if (window.globalHLS) {
										try {
											var level = globalHLS.levelController.levels[globalHLS.levelController.level];
											var str = level.videoCodec + "," + level.audioCodec;
											id("_debug_current_codec").innerHTML = str;
										} catch (e) {
											console.error(e);
										}
									}
								} catch (e) {
									console.error(e);
								}
							});
							run_promise(function () {
								try {
									if (pp.getVideoPlaybackQuality) {
										var pbq = pp.getVideoPlaybackQuality();
										id("_debug_vpd_0").innerHTML = pbq.totalVideoFrames;
										id("_debug_vpd_1").innerHTML = pbq.droppedVideoFrames;
										if (pbq.corruptedVideoFrames) {
											id("_debug_vpd_2").innerHTML = pbq.corruptedVideoFrames;
										} else {
											id("_debug_vpd_2").innerHTML = "?";
										}
									} else if (typeof pp.webkitDecodedFrameCount === "number" && typeof pp.webkitDroppedFrameCount === "number") {
										id("_debug_vpd_0").innerHTML = pp.webkitDecodedFrameCount;
										id("_debug_vpd_1").innerHTML = pp.webkitDroppedFrameCount;
										id("_debug_vpd_2").innerHTML = "?";
									} else {
										id("_debug_vpd_0").innerHTML = "?";
										id("_debug_vpd_1").innerHTML = "?";
										id("_debug_vpd_2").innerHTML = "?";
									}
								} catch (e) {
									console.error(e);
								}
							});
							run_promise(function () {
								try {
									var _pp = id("_primary_player");
									if (_pp == null || sm === "redwood") {
										try {
											_pp = document.getElementsByClassName("video-stream html5-main-video")[0];
										} catch (e) {}
									}
									if (_pp.tagName === "DIV") {
										_pp = _pp.children[0];
									}
									var buffer = _pp.buffered.end(_pp.buffered.length - 1) - _pp.currentTime;
									var n = (buffer / bufferSize) * 100;
									if (n > 100) {
										n = 100;
									} else if (n < 0) {
										n = 0;
									}
									id("__debug_overlay_canvas").style.width = n + "%";
									const t = buffer.toFixed(2);
									id("__debug_canvas_time").innerHTML = t + "s";
									if (buffer > 0 && buffer <= 5) {
										id("__debug_overlay_canvas").style.backgroundColor = "red";
									} else if (buffer > 5 && buffer <= 8) {
										id("__debug_overlay_canvas").style.backgroundColor = "orangered";
									} else if (buffer > 8 && buffer <= 11) {
										id("__debug_overlay_canvas").style.backgroundColor = "orange";
									} else {
										id("__debug_overlay_canvas").style.backgroundColor = "green";
									}
								} catch (e) {
									console.error(e);
								}
							});
							run_promise(function () {
								try {
									if (supportsBitrateUsage) {
										var totalBitrate = 0;
										var currentBitrate = 0;
										if (window.dashjs) {
											if (window.ndashPlayer) {
												const ctv0 = ndashPlayer.getCurrentTrackFor("video");
												totalBitrate += ctv0.bitrateList[ndashPlayer.getQualityFor("video")].bandwidth;
												const cta0 = ndashPlayer.getCurrentTrackFor("audio");
												totalBitrate += cta0.bitrateList[ndashPlayer.getQualityFor("audio")].bandwidth;
											}
											if (window.ndashPlayer) {
												currentBitrate += ndashPlayer.getAverageThroughput("video");
												currentBitrate += ndashPlayer.getAverageThroughput("audio");
											}
										} else if (window.RxPlayer) {
											/* TODO: Implement total bitrate calculations on RxPlayer. */
											if (window.playerInstance) {
												currentBitrate += playerInstance.getAudioRepresentation().bitrate;
												currentBitrate += playerInstance.getVideoRepresentation().bitrate;
											}
										} else {
											console.warn("Unknown backend for bitrate usage.");
											return;
										}
										const usage = ((currentBitrate * 100) / totalBitrate) * 100;
										id("__debug_br_overlay_canvas").style.width = (usage > 100 ? 100 : usage) + "%";
										id("__debug_br_canvas").innerHTML = usage.toFixed(2) + "%";
										if (usage <= 15) {
											id("__debug_br_overlay_canvas").style.backgroundColor = "red";
										} else if (usage > 15 && usage <= 25) {
											id("__debug_br_overlay_canvas").style.backgroundColor = "orangered";
										} else if (usage > 25 && usage <= 60) {
											id("__debug_br_overlay_canvas").style.backgroundColor = "orange";
										} else {
											id("__debug_br_overlay_canvas").style.backgroundColor = "green";
										}
									}
								} catch (e) {
									console.error(e);
								}
							});
							run_promise(function () {
								try {
									function getSyncString(sm) {
										if (sm === undefined) {
											return "...";
										}
										if (window.Config && window.Config.global.experiments && window.Config.global.experiments.use_ios_hls) {
											return "EXPERIMENT_IOS_HLS";
										}
										switch (sm) {
											case "fallback":
												return "Fallback";
											case "nmuxer":
												return "Native (nMuxer)";
											case "dash":
												return "Native (dash.js)";
											case "nplayernx":
												return "nPlayerNX (sync: " + mainPlayer.difference() + ")";
											case "hls":
												return "Native (hls.js)";
											case "redwood":
												return "Native (Redwood-Native)";
											case "rxplayer":
												return "Native (rxPlayer)";
											default:
												return "Unknown (" + sm + ")";
										}
									}
									id("__debug_sync_method").innerHTML = getSyncString(sm);
								} catch (e) {
									console.error(e);
								}
							});
						}, 1000);
					}
					function __debugging_stop() {
						window.clearInterval(window.__debugging_interval);
						hide(id("debug_overlay"));
					}
					function createVisualiser(element) {
						if (window.Audio && window.AudioContext) {
							var canvas, ctx, source, context, analyser, fbc_array, bar_count, bar_pos, bar_width, bar_height;
							run_promise(function () {
								function FrameLooper() {
									const visible = !element.paused && !document.hidden;
									if (visible) {
										window.RequestAnimationFrame =
											window.requestAnimationFrame(FrameLooper) || window.msRequestAnimationFrame(FrameLooper) || window.mozRequestAnimationFrame(FrameLooper) || window.webkitRequestAnimationFrame(FrameLooper);
									} else {
										setTimeout(FrameLooper, 333);
									}
									if (visible) {
										fbc_array = new Uint8Array(analyser.frequencyBinCount);
										bar_count = window.innerWidth / 2;

										analyser.getByteFrequencyData(fbc_array);

										ctx.clearRect(0, 0, canvas.width, canvas.height);
										ctx.fillStyle = "#3f3f3f";

										for (var i = 0; i < bar_count; i++) {
											bar_pos = i * 4;
											bar_width = 2;
											bar_height = -(fbc_array[i] / 2);
											ctx.fillRect(bar_pos, canvas.height, bar_width, bar_height);
										}
									}
								}
								context = new AudioContext({
									latencyHint: "balanced",
									sampleRate: 48000,
								});
								analyser = context.createAnalyser();
								canvas = id("__equalizer_canvas");
								ctx = canvas.getContext("2d");
								source = context.createMediaElementSource(element);

								source.connect(analyser);
								analyser.connect(context.destination);

								FrameLooper();
							});
						}
					}
					if (!window.nTube) window.nTube = {};
					window.nTube.VideoScaling = {
						init: function () {
							//_primary_canvas
							id("_primary_canvas").style.display = "";
							id("_primary_canvas").style.visibility = "";
							id("_primary_canvas").style.width = "100%";
							id("_primary_canvas").style.maxHeight = "90vh";
							id("_primary_player").style.maxHeight = "64px";
						},
						enable: function () {
							const processor = {
								load: function () {
									this.video = id("_primary_player");
									this.canvas = id("_primary_canvas");
									this.canvas.width = this.canvas.getBoundingClientRect().width;
									this.canvas.height = this.canvas.getBoundingClientRect().height;
									this.context = this.canvas.getContext("2d");
									this.timerCallback();
								},
								timerCallback: function () {
									const self = this;
									this.callbackId = setInterval(function () {
										self.canvas.width = self.canvas.getBoundingClientRect().width;
										self.canvas.height = self.canvas.getBoundingClientRect().height;
										nTube.run_promise(function () {
											try {
												console.debug("computeFrame()");
												const canvas = self.canvas;
												const width = self.video.videoWidth;
												const height = self.video.videoHeight;
												self.context.drawImage(self.video, 0, 0, canvas.width, canvas.height);
												if (self.video.paused || self.video.ended) {
													return;
												}
												const count = width * height;
												const data = self.context.getImageData(0, 0, canvas.width, canvas.height);
												const original = new Array(count);
												for (var i = 0; i < count; i++) {
													const index = i << 2;
													original[i] = (data[index + 3] << 24) + (data[index + 2] << 16) + (data[index + 1] << 8) + data[index];
												}
												const result = superxbr(original, width, height);
												const newImageData = self.context.getImageData(0, 0, canvas.width, canvas.height);
												const dest = newImageData.data;
												for (var i = 0; i < count * 4; i++) {
													const index2 = i << 2;
													dest[index2] = result[i] & 255;
													dest[index2 + 1] = (result[i] >> 8) & 255;
													dest[index2 + 2] = (result[i] >> 16) & 255;
													dest[index2 + 3] = (result[i] >> 24) & 255;
												}
												self.context.putImageData(newImageData, 0, 0, 0, 0, canvas.width, canvas.height);
											} catch (e) {
												self.context.drawImage(self.video, 0, 0, canvas.width, canvas.height);
												console.error(e);
											}
										});
									}, 1000 / 24);
								},
							};
							processor.load();
							this.processor = processor;
						},
					};
				</script>
			</div>
			<audio id="_secondary_player" style="visibility: hidden; display: none" autoplay crossorigin="anonymous" controls="true"></audio>
		</div>
		<div class="poly-item" style="border: 1px solid orange; display: none; visibility: hidden" id="error_div">
			<h3 id="error_title" style="margin-top: 5px; margin-bottom: 10px">Error.</h3>
			<p id="error_string" style="margin-top: 5px; margin-bottom: 5px">$Error.string</p>
		</div>
		<div id="misc-prompt-ui" style="color: white; display: none; visibility: hidden"></div>
		<div id="video_flags" class="video_flags">
			<!--<div class="flag_prompt">
				Contains promoted content
			</div>
			<div class="flag_prompt flag_prompt_warn">
				Age-restricted
			</div>-->
		</div>
		<div id="-ntube-info-div" class="poly-item">
			<div style="margin-left: -5px; position: fixed; z-index: -1; width: 100%; height: calc(9.67em); bottom: 0px; left: 9px">
				<canvas id="__equalizer_canvas" style="width: 100%; height: 100%"></canvas>
			</div>
			<div style="position: relative; z-index: 1">
				<div>
					<script defer="defer">
						function toggle(item) {
							var element = id(item);
							var elements = document.getElementsByClassName("dropdown-content");
							for (var i = 0; i < elements.length; i++) {
								var ix = elements[i];
								if (ix !== element) {
									ix.classList.remove("show");
								}
							}
							elements = document.getElementsByClassName("dropdown-content-new");
							for (var i = 0; i < elements.length; i++) {
								var ix = elements[i];
								if (ix !== element) {
									ix.classList.remove("show");
								}
							}
						}
					</script>
					<div class="flex_box_compat flex_wrap_compat" style="vertical-align: middle">
						<div class="flex_box_compat flex_one_compat flex_justify_start_compat flex_wrap_compat" style="flex-basis: 65%; -webkit-flex-basis: 65%; -moz-flex-basis: 65%; -ms-flex-basis: 65%; overflow: hidden">
							<h3
								id="video_title_localized"
								style="vertical-align: middle; font-size: calc(100% - 0.1vh); text-overflow: ellipsis; margin-top: 5px; margin-bottom: 0px; display: none; visibiltiy: hidden"
								title="Localized Title: This title does NOT represent the original video's title."
							>
								Loading...
							</h3>
							<hr class="flex_hr_compat" />
							<h3 id="video_title" class="width_max_content" style="vertical-align: middle; font-size: calc(100% - -0.06vw); text-overflow: ellipsis; margin-top: 5px; margin-bottom: 2px">Loading...</h3>
						</div>
						<div class="flex_box_compat flex_one_compat flex_justify_end_compat" style="margin-top: 5px; height: 0px; margin-right: 8px">
							<style>
								.dropbtn {
									color: white;
									background: inherit;
									padding: 16px;
									font-size: 16px;
									border: none;
									padding-top: 5px;
									padding-left: 5px;
									width: 40px;
									height: 40px;
								}

								.dropdisable {
									-webkit-filter: brightness(50%);
									filter: brightness(50%);
								}

								.fixed_size_btn {
									width: 2.5em;
									height: 2.5em;
								}
							</style>
							<button class="fixed_size_btn" style="border: none; background: inherit; display: none; visibility: hidden; color: inherit; font-family: inherit" id="button-cast" title="Cast to external device.">
								<img decoding="async" style="vertical-align: middle; width: 2.5em; height: 2.5em" src="resources/icons/cast.svg" alt="Cast Video Icon." />
							</button>
							<button class="fixed_size_btn" style="border: none; background: inherit; color: inherit; font-family: inherit" id="button-watch-later" title="Watch Later.">
								<img decoding="async" style="vertical-align: middle; width: 2.5em; height: 2.5em" src="resources/icons/clock.png" alt="Watch Later Icon." svg-src-alt="resources/icons/clock.svg" />
							</button>
							<button class="fixed_size_btn" style="border: none; background: inherit; color: inherit; font-family: inherit" id="button-share-video" title="Share Video.">
								<img decoding="async" style="vertical-align: middle; width: 2.5em; height: 2.5em" src="resources/icons/share.svg" alt="Share Video Icon." />
							</button>
							<button class="fixed_size_btn" style="border: none; background: inherit; color: inherit; font-family: inherit" id="button-cinema-mode" title="Cinema Mode.">
								<img decoding="async" style="vertical-align: middle; width: 2.5em; height: 2.5em" src="resources/icons/full_window.svg" alt="Enter Cinema Mode Icon." />
							</button>
							<script defer="defer">
								window.isInCinema = false;
								function cinema_mode_toggle() {
									if (window.isInCinema) {
										id("_primary_player").style.width = "100%";
										id("_primary_player").style.height = "auto";
										id("_primary_player").style.maxHeight = "90vh";
										id("actual-primary-video-div").style.width = "";
										id("actual-primary-video-div").style.height = "";
										id("video_primary_div").style.position = "";
										id("video_primary_div").style.width = "";
										id("video_primary_div").style.height = "";
										id("video_primary_div").style.marginLeft = "";
										id("video_primary_div").style.zIndex = "";
										id("video_primary_div").style.backdropFilter = "";
										id("video_primary_div").style.marginTop = "";
										hide(id("cinema_mode_toggle_overlay"));
										id("video_primary_div").style.backgroundColor = "";
										document.getElementsByTagName("body")[0].style.overflowY = "";
									} else {
										id("_primary_player").style.width = "100%";
										id("_primary_player").style.height = "100%";
										id("_primary_player").style.maxHeight = "";
										id("actual-primary-video-div").style.width = "100%";
										id("actual-primary-video-div").style.height = "100%";
										id("video_primary_div").style.position = "fixed";
										id("video_primary_div").style.width = "100%";
										id("video_primary_div").style.height = "100%";
										id("video_primary_div").style.marginLeft = "-9px";
										id("video_primary_div").style.zIndex = "16";
										id("video_primary_div").style.backdropFilter = "blur(5px)";
										id("video_primary_div").style.marginTop = "-38px";
										show(id("cinema_mode_toggle_overlay"));
										id("video_primary_div").style.backgroundColor = "rgba(0, 0, 0, 0.99)";
										document.getElementsByTagName("body")[0].style.overflowY = "hidden";
									}
									window.isInCinema = !window.isInCinema;
								}
								id("button-cinema-mode").onclick = function () {
									cinema_mode_toggle();
								};
								id("button-share-video").onclick = function () {
									if (isHidden(id("share_overlay"))) {
										id("share_overlay").style.display = "";
										id("share_overlay").style.visibility = "";
									} else {
										id("share_overlay").style.display = "none";
										id("share_overlay").style.visibility = "hidden";
										hide(id("share_overlay_output"));
										show(id("share_overlay_format_selector"));
									}
								};
								var __added_to_watch_later = false;
								id("button-watch-later").onclick = function () {
									if (__added_to_watch_later) {
										displayMessage("Watch Later.", "This video has already been added to your watch later queue.", 5000);
										return;
									}
									if (!window["jsonObject"] || window.jsonObject === null || window.jsonObject === undefined) {
										displayMessage("Watch Later.", "Missing required data to add a video, try again in a moment.", 5000);
										return;
									}
									if (Settings.exists("ntube_watch_later")) {
										const wl_obj = Settings.load("ntube_watch_later");
										const date = new Date();
										wl_obj["videos"].push({
											title: jsonObject.metadata.title,
											author: jsonObject.metadata.author,
											authorID: jsonObject.metadata.authorID,
											length: jsonObject.metadata.duration,
											videoID: getQueryVariable("v"),
											thumbnailLevel: jsonObject.metadata.thumbnailLevel,
											added: date,
										});
										if (Settings.save("ntube_watch_later", wl_obj)) {
											displayMessage("Watch Later.", "Added to your watch later queue.", 5000);
											__added_to_watch_later = true;
										} else {
											displayMessage("Watch Later.", "Failed to add to queue.", 8000);
										}
									} else {
										const date1 = new Date();
										const wl_obj1 = {
											videos: [
												{
													title: jsonObject.metadata.title,
													author: jsonObject.metadata.author,
													authorID: jsonObject.metadata.authorID,
													length: jsonObject.metadata.duration,
													videoID: getQueryVariable("v"),
													thumbnailLevel: jsonObject.metadata.thumbnailLevel,
													added: date1,
												},
											],
											version: 1,
										};
										if (Settings.save("ntube_watch_later", wl_obj1)) {
											displayMessage("Watch Later.", "Added to your watch later queue.", 5000);
											__added_to_watch_later = true;
										} else {
											displayMessage("Watch Later.", "Failed to add to queue.", 8000);
										}
									}
								};
								try {
									if (isChromeFunc && isChromeFunc()) {
										hide(id("button-cinema-mode"));
									}
								} catch (ex) {
									console.error(ex);
								}
							</script>
							<button class="fixed_size_btn" style="border: none; background: inherit; display: none; visibility: hidden; font-family: inherit; color: inherit" id="button-nmusic-play" title="Play with nMusic." disabled="true">
								<img decoding="async" class="dropdisable" style="vertical-align: middle; width: 2.5em; height: 2.5em" src="resources/icons/music.svg" alt="Play with nMusic icon." />
							</button>
							<script defer="defer">
								if (window.BroadcastChannel) {
									id("button-nmusic-play").disabled = false;
									id("button-nmusic-play").children[0].classList.remove("dropdisable");
									id("button-nmusic-play").onclick = function () {
										const n = prompt("Enter your Session ID.");
										if (n === null || n === undefined || n.length !== 36) {
											return;
										} else {
											const videoID = getQueryVariable("v");
											if (videoID === null || videoID === undefined || videoID.length === 0) {
											} else {
												const bc = new BroadcastChannel(n);
												bc.onmessage = function (msg) {
													const d = JSON.parse(msg.data);
													if (d["type"] === "nMusic_response") {
														if (d["message"] === "OK") {
															displayMessage("Play with nMusic.", "Sent " + videoID + " to your playlist.", 5000);
														} else {
															displayMessage("Play with nMusic.", "Failed to send to your playlist.", 5000);
														}
														bc.close();
													}
												};
												var ms = {};
												ms["type"] = "nMusic_submit";
												if (!window.jsonObject) {
													ms["url"] = "https://www.youtube.com/watch?v=" + videoID;
													ms["videoID"] = videoID;
												} else {
													ms["url"] = JSON.stringify(window.jsonObject);
													ms["videoID"] = videoID;
												}
												bc.postMessage(JSON.stringify(ms));
											}
										}
									};
								} else {
								}
							</script>
							<script defer="defer"></script>
						</div>
						<hr class="flex_hr_compat" />
						<!-- FIXME: For some reason we overflow without hinting at the full viewport width??? -->
						<div class="flex_box_compat flex_wrap_compat flex_one_compat flex_justify_start_compat flex_align_start_compat" style="width: 100%">
							<div class="flex_box_compat flex_wrap_compat">
								<img
									decoding="async"
									loading="lazy"
									style="display: inline; vertical-align: bottom; margin-right: 5px"
									src="resources/icons/account.png"
									alt="Author Indicator"
									svg-src-alt="resources/icons/account.svg"
									svg-width-alt="20px"
									svg-height-alt="20px"
								/>
								<p class="flex_no_margins" style="display: inline; vertical-align: bottom" id="channel_name">
									<a href="#" style="color: inherit; text-decoration: underline dotted gray" id="video_author">...</a>
								</p>
							</div>
							<p class="flex_box_compat flex_wrap_compat flex_no_margins flex_horizontal_spacing">&centerdot;</p>
							<div class="flex_box_compat flex_wrap_compat">
								<img
									decoding="async"
									loading="lazy"
									style="display: inline; vertical-align: bottom; margin-right: 5px"
									src="resources/icons/clock.png"
									alt="Duration Indicator"
									svg-src-alt="resources/icons/clock.svg"
									svg-width-alt="20px"
									svg-height-alt="20px"
								/>
								<p class="flex_no_margins" style="display: inline; vertical-align: bottom" id="video_duration" title="Duration">00:00</p>
							</div>
							<p class="flex_box_compat flex_wrap_compat flex_no_margins flex_horizontal_spacing">&centerdot;</p>
							<div class="flex_box_compat flex_wrap_compat">
								<img
									decoding="async"
									loading="lazy"
									style="display: inline; vertical-align: bottom; margin-right: 5px"
									src="resources/icons/eye.png"
									alt="View Count Indicator"
									svg-src-alt="resources/icons/eye.svg"
									svg-width-alt="20px"
									svg-height-alt="20px"
								/>
								<p class="flex_no_margins" style="display: inline; vertical-align: bottom" id="video_viewcount" title="Viewers">0</p>
							</div>
							<p class="flex_box_compat flex_wrap_compat flex_no_margins flex_horizontal_spacing">&centerdot;</p>
							<p class="flex_box_compat flex_wrap_compat flex_no_margins" id="video_likes" title="Like Count"></p>
							<div id="video_rating_pre" title="No like or dislike data provided." style="display: inline-flex; width: 200px; height: 10px; background-color: red; border-radius: 25px; margin-top: 5px; vertical-align: middle">
								<div style="display: inline-flex; width: 100%; height: 10px; background-color: green; border-radius: 25px; vertical-align: super" id="video_rating_g"></div>
							</div>
							<p class="flex_no_margins" class="flex_box_compat flex_wrap_compat" id="video_dislikes" title="Dislike Count"></p>
						</div>
					</div>
					<!--<div style="float: left; vertical-align: middle; max-width: 73.9vw; min-width: 60%; width: auto;">
						<h3 id="video_title_localized" style="vertical-align: middle; font-size: calc(100% - 0.1000vw); text-overflow: ellipsis; margin-top: 5px; margin-bottom: 0px; display: none; visibiltiy: hidden;" title="Localized Title: This title does NOT represent the original video's title.">Loading...</h3>
						<h3 id="video_title" style="vertical-align: middle;font-size: calc(100% - -0.0600vw); text-overflow: ellipsis; margin-top: 5px; margin-bottom: 2px;">Loading...</h3>
					</div>-->
					<!--<div style="float: right;vertical-align: middle; height: 0px; width: max-content; margin-top: 5px">
						
					</div>-->
				</div>
				<div>
					<!--<div style="float: right;">
						<img decoding="async" id="video_special_icon" alt="" />
					</div>
					<div style="clear: both;"></div>-->
				</div>
				<button class="collapsible">
					<div>
						<img style="display: inline; vertical-align: middle" decoding="async" loading="lazy" src="resources/icons/description.png" svg-src-alt="resources/icons/description.svg" svg-width-alt="20px" svg-height-alt="20px" />
						<p style="display: inline; vertical-align: middle">Description.</p>
					</div>
				</button>
				<div class="content">
					<style>
						a {
							color: inherit;
							text-decoration: underline dotted white;
						}
					</style>
					<p id="video_description" style="font-size: 1em; white-space: normal; overflow-wrap: break-word">No description provided.</p>
				</div>
				<button id="video_chapters_button" class="collapsible" style="display: none; visibility: hidden">
					<div>
						<img
							style="display: inline; vertical-align: middle"
							decoding="async"
							loading="lazy"
							src="resources/icons/chapters_icon_small.png"
							svg-src-alt="resources/icons/chapters_icon_dynamic.svg"
							svg-width-alt="20px"
							svg-height-alt="20px"
						/>
						<p style="display: inline; vertical-align: middle">Chapters.</p>
					</div>
				</button>
				<div class="content" maxHeight="force" style="padding: 0px">
					<style>
						a {
							color: inherit;
							text-decoration: underline dotted white;
						}

						.video-chapter {
							display: inline-flex !important;
							flex-basis: 45vh;
						}

						.video-chapter-unwanted {
							background: repeating-linear-gradient(0deg, transparent, rgb(223 185 0 / 20%) 16px);
						}

						.video-chapter-poly {
							padding-left: 0px !important;
							margin-right: 2px;
							padding-bottom: 2px;
							margin-bottom: 2px !important;
						}

						.video-chapter-idiv {
							display: table-cell;
							margin: auto 0px;
						}

						@media only screen and (max-width: 600px) {
							.video-chapter {
								flex-basis: 100vw !important;
								width: 100% !important;
							}
						}
					</style>
					<center id="video_chapters" class="flex_box_compat flex_wrap_compat flex_direction_row_compat" style="text-align: left; margin-top: 5px; justify-content: center">
						<div class="video-chapter poly-item video-chapter-poly" style="margin-bottom: 5px; padding-left: 0px">
							<div class="video-chapter-idiv" style="vertical-align: middle; display: table-cell; padding-left: 0px; padding-right: 5px">
								<h3 style="vertical-align: middle; margin: 0px auto">You're waifu</h3>
								<p style="vertical-align: bottom; margin: 0px; font-size: small">is trash.</p>
							</div>
						</div>
					</center>
				</div>
				<button id="video_heatmap_button" class="collapsible" style="display: none; visibility: hidden">
					<div>
						<img style="display: inline; vertical-align: middle" decoding="async" loading="lazy" src="resources/icons/heatmap.png" svg-src-alt="resources/icons/heatmap.svg" svg-width-alt="20px" svg-height-alt="20px" />
						<p style="display: inline; vertical-align: middle">Heatmap.</p>
					</div>
				</button>
				<div class="content">
					<div style="padding-bottom: 5px">
						<canvas id="heatmap-canvas" style="height: 192px; width: 90%"> I think your browser might be out of date. </canvas>
					</div>
				</div>
				<button class="collapsible">
					<div>
						<img
							style="display: inline; vertical-align: middle"
							decoding="async"
							loading="lazy"
							src="resources/icons/advanced_stuff.png"
							svg-src-alt="resources/icons/advanced_stuff.svg"
							svg-width-alt="20px"
							svg-height-alt="20px"
						/>
						<p style="display: inline; vertical-align: middle">Advanced stuff.</p>
					</div>
				</button>
				<div class="content">
					<div style="padding-bottom: 5px">
						<p style="font-size: large; font-weight: bold; line-height: 20%; padding-bottom: 0px">Upload Information.</p>
						<div class="video-advanced-sep" style="border-top: 1px solid green">
							Upload Date: <span id="upload_date_string">N/A</span> <br />
							Publish Date: <span id="publish_date_string">N/A</span> <br />
							Family Friendly: <span id="ff_string">N/A</span>
						</div>
						<p style="font-size: large; font-weight: bold; line-height: 20%; padding-bottom: 0px">Tags.</p>
						<div class="video-advanced-sep" id="video_tags" style="border-top: 1px solid green">There doesn't seem to be any tags on this video.</div>
						<p style="font-size: large; font-weight: bold; line-height: 20%; padding-bottom: 0px">Super Tags.</p>
						<div class="video-advanced-sep" id="video_super_tags" style="border-top: 1px solid green">There doesn't seem to be any super tags on this video.</div>
						<p style="font-size: large; font-weight: bold; line-height: 20%; padding-bottom: 0px">Audio Information.</p>
						<div class="video-advanced-sep" style="border-top: 1px solid green">dB Audio Correction: <span id="ldb_date_string">N/A</span></div>
					</div>
				</div>
				<button class="collapsible">
					<div>
						<img
							style="display: inline; vertical-align: middle"
							decoding="async"
							loading="lazy"
							src="resources/icons/playback_settings.png"
							svg-src-alt="resources/icons/playback_settings.svg"
							svg-width-alt="20px"
							svg-height-alt="20px"
						/>
						<p style="display: inline; vertical-align: middle">Playback Settings.</p>
					</div>
				</button>
				<div class="content" maxHeight="380px" style="padding: 0px !important; margin-left: -5px">
					<style>
						.new-cfg-tab {
							overflow: hidden;
							background-color: gray;
						}

						.new-cfg-tab button {
							background-color: inherit;
							float: left;
							border: none;
							outline: none;
							cursor: pointer;
							padding: 14px 16px;
							transition: 0.3s;
							font-family: inherit;
						}

						.new-cfg-tab button:hover {
							background-color: darkgray;
						}

						.new-cfg-tab button.active {
							background-color: darkgray;
						}

						.tabcontent {
							display: none;
							padding: 6px 12px;
							border-top: none;
							margin-left: -5px;
							animation: fadeEffect 1s;
						}

						@keyframes fadeEffect {
							from {
								opacity: 0;
							}

							to {
								opacity: 1;
							}
						}
					</style>
					<script defer="defer">
						function __new_config_ui_open(event, tab) {
							var i, tabcontent, tablinks;
							tabcontent = document.getElementsByClassName("tabcontent");
							for (i = 0; i < tabcontent.length; i++) {
								tabcontent[i].style.display = "none";
							}
							tablinks = document.getElementsByClassName("tablinks");
							for (i = 0; i < tablinks.length; i++) {
								tablinks[i].className = tablinks[i].className.replace(" active", "");
							}
							id(tab).style.display = "block";
							event.currentTarget.className += " active";
						}
					</script>
					<div class="new-cfg-tab" style="margin-left: -5px">
						<button id="--new-cfg-tab-video-btn" class="tablinks" onclick="__new_config_ui_open(event, 'newcfg-Settings')" style="display: none; visibility: hidden">
							<div>
								<img
									style="display: inline; vertical-align: middle"
									decoding="async"
									loading="lazy"
									src="resources/icons/settings_small.png"
									svg-src-alt="resources/icons/settings_updated.svg"
									svg-width-alt="20px"
									svg-height-alt="20px"
								/>
								<p style="display: inline; vertical-align: middle">Video.</p>
							</div>
						</button>
						<button id="--new-cfg-tab-locale-btn" class="tablinks" onclick="__new_config_ui_open(event, 'newcfg-Locale')" style="display: none; visibility: hidden">
							<div>
								<img style="display: inline; vertical-align: middle" decoding="async" loading="lazy" src="resources/icons/locale.png" svg-src-alt="resources/icons/locale.svg" svg-width-alt="20px" svg-height-alt="20px" />
								<p style="display: inline; vertical-align: middle">Locale.</p>
							</div>
						</button>
						<button class="tablinks active" onclick="__new_config_ui_open(event, 'newcfg-Audio')">
							<div>
								<img
									style="display: inline; vertical-align: middle"
									decoding="async"
									loading="lazy"
									src="resources/icons/audio_icon_small.png"
									svg-src-alt="resources/icons/audio_icon_dynamic.svg"
									svg-width-alt="20px"
									svg-height-alt="20px"
								/>
								<p style="display: inline; vertical-align: middle">Audio.</p>
							</div>
						</button>
						<button class="tablinks" onclick="__new_config_ui_open(event, 'newcfg-Downloads')">
							<div>
								<img
									style="display: inline; vertical-align: middle"
									decoding="async"
									loading="lazy"
									src="resources/icons/download_icon_small.png"
									svg-src-alt="resources/icons/download.svg"
									svg-width-alt="20px"
									svg-height-alt="20px"
								/>
								<p style="display: inline; vertical-align: middle">Downloads.</p>
							</div>
						</button>
					</div>
					<div id="newcfg-Settings" class="tabcontent" style="display: none">
						<h3 style="margin-top: 5px; margin-bottom: 5px">Video.</h3>
						<div id="nplayernx_quality_sel">
							<p>
								Quality.<span id="quality_dropdown" style="display: none; visibility: hidden">&nbsp;(Current Quality: <span id="quality_dropdown_string">720p</span>)</span>
							</p>
							<div style="background-color: inherit; margin-right: 5px" id="_ntube_patch_selectors">
								<!--background-color: white;-->
								<select class="flatItem videoselect" id="_ntube_video_qualities" style="background-color: white; color: black; width: 100%">
									<option disabled="true">Loading...</option>
								</select>
								<script defer="defer">
									function isChrome() {
										try {
											return typeof window.chrome === "object" && (typeof window.chrome.runtime === "object" || typeof window.chrome.csi === "function");
										} catch (e) {
											return true;
										}
									}

									if (!isChrome()) {
										var selPatch = id("_ntube_patch_selectors");
										selPatch.style.backgroundColor = "inherit";
										var qual = id("_ntube_video_qualities");
										qual.style.color = "inherit";
										qual.style.backgroundColor = "inherit";
									}
								</script>
							</div>
							<button style="margin-top: 5px; font-size: medium; font-family: inherit; color: inherit; background-color: inherit; border: 1px solid orangered" id="--trigger-debugging">Enable Debugging.</button>
							<script defer="defer">
								id("--trigger-debugging").onclick = function () {
									window.__debugging_start();
								};
							</script>
							<p style="color: orangered">NOTE: This only applies to nPlayerNX at the moment, further support coming soon.</p>
						</div>
					</div>
					<div id="newcfg-Locale" class="tabcontent" style="display: none">
						<div>
							<h3 style="margin-top: 5px; margin-bottom: 5px; float: left">Locale.</h3>
							<select class="flatItem videoselect" id="_ntube_audio_locale" style="margin-top: 5px; background-color: white; color: black; width: 60vw; float: right">
								<option disabled="true">Loading...</option>
							</select>
							<div style="clear: both"></div>
						</div>
						<p style="margin-top: 5px; margin-bottom: 5px">This will change the audio language (track) used in the video, if available.</p>
					</div>
					<div id="newcfg-Audio" class="tabcontent" style="display: block">
						<style>
							.range {
								-webkit-appearance: none;
								-moz-appearance: none;
								width: 200px;
								margin-top: 10px;
							}

							.range[type="range"]::-webkit-slider-runnable-track {
								-webkit-appearance: none;
								background: rgba(59, 173, 227, 1);
								background: -moz-linear-gradient(45deg, rgba(59, 173, 227, 1) 0%, rgba(87, 111, 230, 1) 25%, rgba(152, 68, 183, 1) 51%, rgba(255, 53, 127, 1) 100%);
								background: -webkit-gradient(
									left bottom,
									right top,
									color-stop(0%, rgba(59, 173, 227, 1)),
									color-stop(25%, rgba(87, 111, 230, 1)),
									color-stop(51%, rgba(152, 68, 183, 1)),
									color-stop(100%, rgba(255, 53, 127, 1))
								);
								background: -webkit-linear-gradient(45deg, rgba(59, 173, 227, 1) 0%, rgba(87, 111, 230, 1) 25%, rgba(152, 68, 183, 1) 51%, rgba(255, 53, 127, 1) 100%);
								background: -o-linear-gradient(45deg, rgba(59, 173, 227, 1) 0%, rgba(87, 111, 230, 1) 25%, rgba(152, 68, 183, 1) 51%, rgba(255, 53, 127, 1) 100%);
								background: -ms-linear-gradient(45deg, rgba(59, 173, 227, 1) 0%, rgba(87, 111, 230, 1) 25%, rgba(152, 68, 183, 1) 51%, rgba(255, 53, 127, 1) 100%);
								background: linear-gradient(45deg, rgba(59, 173, 227, 1) 0%, rgba(87, 111, 230, 1) 25%, rgba(152, 68, 183, 1) 51%, rgba(255, 53, 127, 1) 100%);
								filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3bade3 ', endColorstr='#ff357f ', GradientType=1);
								height: 2px;
							}

							.range[type="range"]:focus {
								outline: none;
							}

							.range[type="range"]::-moz-range-track {
								-moz-appearance: none;
								background: rgba(59, 173, 227, 1);
								background: -moz-linear-gradient(45deg, rgba(59, 173, 227, 1) 0%, rgba(87, 111, 230, 1) 25%, rgba(152, 68, 183, 1) 51%, rgba(255, 53, 127, 1) 100%);
								background: -webkit-gradient(
									left bottom,
									right top,
									color-stop(0%, rgba(59, 173, 227, 1)),
									color-stop(25%, rgba(87, 111, 230, 1)),
									color-stop(51%, rgba(152, 68, 183, 1)),
									color-stop(100%, rgba(255, 53, 127, 1))
								);
								background: -webkit-linear-gradient(45deg, rgba(59, 173, 227, 1) 0%, rgba(87, 111, 230, 1) 25%, rgba(152, 68, 183, 1) 51%, rgba(255, 53, 127, 1) 100%);
								background: -o-linear-gradient(45deg, rgba(59, 173, 227, 1) 0%, rgba(87, 111, 230, 1) 25%, rgba(152, 68, 183, 1) 51%, rgba(255, 53, 127, 1) 100%);
								background: -ms-linear-gradient(45deg, rgba(59, 173, 227, 1) 0%, rgba(87, 111, 230, 1) 25%, rgba(152, 68, 183, 1) 51%, rgba(255, 53, 127, 1) 100%);
								background: linear-gradient(45deg, rgba(59, 173, 227, 1) 0%, rgba(87, 111, 230, 1) 25%, rgba(152, 68, 183, 1) 51%, rgba(255, 53, 127, 1) 100%);
								filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3bade3 ', endColorstr='#ff357f ', GradientType=1);
								height: 2px;
							}

							.range[type="range"]::-webkit-slider-thumb {
								-webkit-appearance: none;
								border: 2px solid;
								border-radius: 50%;
								height: 15px;
								width: 15px;
								max-width: 80px;
								position: relative;
								bottom: 6px;
								background-color: #1d1c25;
								cursor: -webkit-grab;

								-webkit-transition: border 1000ms ease;
								transition: border 1000ms ease;
							}

							.range[type="range"]::-moz-range-thumb {
								-moz-appearance: none;
								border: 2px solid;
								border-radius: 50%;
								height: 15px;
								width: 15px;
								max-width: 80px;
								position: relative;
								bottom: 11px;
								background-color: #1d1c25;
								cursor: -moz-grab;
								-moz-transition: border 1000ms ease;
								transition: border 1000ms ease;
							}

							.range.blue::-webkit-slider-thumb {
								border-color: rgb(59, 173, 227);
							}

							.range.ltpurple::-webkit-slider-thumb {
								border-color: rgb(87, 111, 230);
							}

							.range.purple::-webkit-slider-thumb {
								border-color: rgb(152, 68, 183);
							}

							.range.pink::-webkit-slider-thumb {
								border-color: rgb(255, 53, 127);
							}

							.range.blue::-moz-range-thumb {
								border-color: rgb(59, 173, 227);
							}

							.range.ltpurple::-moz-range-thumb {
								border-color: rgb(87, 111, 230);
							}

							.range.purple::-moz-range-thumb {
								border-color: rgb(152, 68, 183);
							}

							.range.pink::-moz-range-thumb {
								border-color: rgb(255, 53, 127);
							}

							input[type="range"]::-webkit-slider-thumb:active {
								cursor: -webkit-grabbing;
							}

							input[type="range"]::-moz-range-thumb:active {
								cursor: -moz-grabbing;
							}
						</style>
						<img
							loading="lazy"
							decoding="async"
							style="display: inline-block; vertical-align: middle; width: 24px; height: 24px"
							title="QualiGain by nTube. Designed to make audio both better and worse by correcting YouTube's audio gain correction."
							alt="QualiGain Logo"
							src="./resources/icons/specific/qualigain/qualigain_logo_standard_64px.png"
						/>
						<h3 style="margin-top: 5px; margin-bottom: 10px; display: inline-block; vertical-align: sub">Audio.</h3>
						<div>
							<p style="float: left; vertical-align: middle; margin-bottom: 19px; margin-top: 0px">Enable QualiGain.</p>
							<input id="audio-gain-enable" style="float: right; vertical-align: middle; margin-top: 5px; display: block" type="checkbox" />
							<script defer="defer">
								const AUDIO_GAIN_USE_LESS_STABLE_VAR = false;
								function audio_gain_new_alg(x) {
									if (AUDIO_GAIN_USE_LESS_STABLE_VAR) {
										if (window.Config && window.Config.global && window.Config.global.experiments && window.Config.global.experiments.inv_new_audio_alg) {
											var f = x * Math.sin(Math.pow(x, 3));
											if (f < 0) {
												f /= -1;
											}
											return f;
										} else {
											return 16 - x * Math.sin(Math.pow(x, 3));
										}
									} else {
										if (window.Config && window.Config.global && window.Config.global.experiments && window.Config.global.experiments.inv_new_audio_alg) {
											var f = x * Math.cos(Math.pow(x, 2));
											if (f < 0) {
												f /= -1;
											}
											return f;
										} else {
											return 16 - x * Math.cos(Math.pow(x, 2));
										}
									}
								}
								function audio_check() {
									if (!window.AudioContext) {
										alert(":/\nAudioContext API is missing.\nSorry about that.");
										return;
									}
									if (nTube.Audio.context == null) {
										nTube.Audio.context = new AudioContext({
											latencyHint: "balanced",
											sampleRate: 48000,
										});
									}
									if (nTube.Audio.source == null) {
										function getPlayer() {
											if (document.getElementById("_primary_player") === null) {
												try {
													return document.getElementsByClassName("video-stream html5-main-video")[0];
												} catch (e) {
													return null;
												}
											} else {
												return id("_primary_player");
											}
										}
										nTube.Audio.source = nTube.Audio.context.createMediaElementSource(getPlayer()); // TODO: May this work with nPlayer too.
										id("audio-gain-enable").checked = true;
										id("audio-gain-enable").disabled = true;
									}
									if (nTube.Audio.gainNode == null) {
										nTube.Audio.gainNode = nTube.Audio.context.createGain();
										nTube.Audio.gainNode.gain.value = 0;
										nTube.Audio.source.connect(nTube.Audio.gainNode);
										nTube.Audio.gainNode.connect(nTube.Audio.context.destination);
									}
								}
								id("audio-gain-enable").onclick = function () {
									const value = id("audio-gain-enable").value;
									audio_check();
									if (nTube.Audio.gainNode != null) {
										const o = id("audio-gain").value;
										if (o == 9) {
											var v = 1;
											try {
												v = jsonObject.metadata.extended.rawLoudnessDb;
												if (window.Config && window.Config.global && window.Config.global.experiments && window.Config.global.experiments.use_new_audio_alg) {
													const _v = v;
													v = audio_gain_new_alg(v);
													v -= 1;
													console.debug("onclick::audio_gain_new_alg: " + v + " [for: " + _v + "]");
												} else {
													if (v < -1) v /= -1;
													if (v < 1) {
														v = 1;
													}
													if (v >= 9) {
														v -= 4;
													} else if (v >= 6) {
														v -= 2;
													} else if (v <= 0.3) {
														v += 1;
													}
												}
											} catch (e) {}
											nTube.Audio.gainNode.gain.value = value ? (v == 1 ? 1 : 1 + v / 10) : 1;
										} else {
											nTube.Audio.gainNode.gain.value = value ? (o == 10 ? 1 : o / 10) : 1;
										}
									}
								};
							</script>
							<div style="clear: both"></div>
						</div>
						<div>
							<input id="audio-gain" type="range" class="range purple" min="9" max="110" value="9" step="1" style="float: left; background: inherit; margin-top: 0px; width: 60%; vertical-align: middle" />
							<p style="float: right; margin-right: 10px; margin-top: -3px; vertical-align: middle"><span id="audio-gain-label">Automatic</span> dB</p>
							<script defer="defer">
								if (!nTube) window.nTube = {};
								nTube.Audio = { context: null, gainNode: null, source: null };
								id("audio-gain").value = 9;
								id("audio-gain").oninput = function () {
									const value = id("audio-gain").value;
									if (value <= 9) {
										id("audio-gain-label").innerHTML = "Automatic";
										audio_check();
										if (nTube.Audio.gainNode != null) {
											var v = 1;
											try {
												v = jsonObject.metadata.extended.rawLoudnessDb;
												if (window.Config && window.Config.global && window.Config.global.experiments && window.Config.global.experiments.use_new_audio_alg) {
													const _v = v;
													v = audio_gain_new_alg(v);
													v -= 1;
													console.debug("oninput::audio_gain_new_alg: " + v + " [for: " + _v + "]");
												} else {
													if (v < -1) v /= -1;
													if (v < 1) {
														v = 1;
													}
													if (v >= 9) {
														v -= 4;
													} else if (v >= 6) {
														v -= 2;
													} else if (v <= 0.3) {
														v += 1;
													}
												}
											} catch (e) {}
											nTube.Audio.gainNode.gain.value = v == 1 ? 1 : 1 + v / 10;
										}
									} else {
										const tv = value <= 9 ? 1 : value / 10;
										id("audio-gain-label").innerHTML = value <= 9 ? 0 : (value - 10) / 10;
										audio_check();
										if (nTube.Audio.gainNode != null) {
											nTube.Audio.gainNode.gain.value = tv;
										}
									}
								};
							</script>
							<div style="clear: both"></div>
						</div>
						<div class="poly-item" style="width: fit-content; margin: 0 auto; padding-right: 3px">
							<span class="warn warning" style="vertical-align: middle; margin-bottom: 5px"></span>
							<p style="display: inline-block; margin-top: 5px; margin-bottom: 5px; color: orangered; font-size: medium; vertical-align: middle; text-overflow: clip; overflow-wrap: break-word">
								High volumes may result in damage to hearing over long periods! Use some common sense. (if you have any)
							</p>
						</div>
						<h3>Playback Volume.</h3>
						<div>
							<input id="volume" type="range" class="range purple" min="0" max="100" value="100" step="1" style="float: left; background: inherit; margin-top: 0px; width: 60%" />
							<p id="volume_label" style="float: right; margin-right: 10px; margin-top: -3px">100%</p>
							<div style="clear: both"></div>
							<script defer="defer">
								id("volume").oninput = function () {
									const value = id("volume").value;
									id("volume_label").innerHTML = value + "%";
									id("_secondary_player").volume = value != 0 ? value / 100 : 0;
									var pp = id("_primary_player");
									if (pp == null) {
										try {
											pp = document.getElementsByClassName("video-stream html5-main-video")[0];
										} catch (e) {}
									}
									if (pp.tagName === "DIV") {
										pp = pp.children[0];
									}
									pp.volume = value != 0 ? value / 100 : 0;
								};
							</script>
						</div>
					</div>
					<div id="newcfg-Downloads" class="tabcontent" style="display: none">
						<h3 style="margin-top: 5px; margin-bottom: 10px">Downloads.</h3>
						<select id="ntube-dropdown-download-select" style="background-color: white; color: black; width: calc(100% - 5px)">
							<option disabled="true">Loading...</option>
						</select>
						<center>
							<button id="ntube-dropdown-download-button" style="font-family: inherit; color: inherit; background-color: inherit; border: 1px solid green; padding: 5px">Download.</button>
						</center>
					</div>
				</div>
			</div>
		</div>
		<style>
			noindex:-o-prefocus,
			#ntube-dropdown-download-select {
				width: 100%;
				/* Opera 12.xx Fix */
			}

			._playlist_sub_bar {
				display: inline-flex;
				-moz-flex-wrap: wrap;
				-webkit-flex-wrap: wrap;
				-webkit-flex-wrap: wrap;
				-ms-flex-wrap: wrap;
				flex-wrap: wrap;
				align-items: center;
				vertical-align: middle;
				text-align: center;
				justify-content: center;
				width: 100%;
			}

			._playlist_sub_bar_el {
				margin-right: 5px;
			}
		</style>
		<div id="__pl_upnext" class="poly-item" style="display: none; visibility: hidden">
			<h3 id="__pl_header" style="margin-bottom: 0px; margin-top: 5px">Playlist.</h3>
			<h4 style="margin-top: 5px; margin-bottom: 10px">Up Next.</h4>
			<!-- TODO(mainline): Migrate this to FlexBox. -->
			<div class="related-video poly-item related-video-poly" style="margin-bottom: 5px; width: calc(100% - 5px) !important; padding-bottom: 0px !important">
				<a id="__pl_upnext_skip" href="#">
					<img id="__pl_upnext_img" style="vertical-align: middle; display: table-row; width: 160px; height: 90px" loading="lazy" decoding="async" referrerpolicy="no-referrer" src="" />
				</a>
				<div class="related-video-idiv" style="vertical-align: middle; display: table-cell; padding-left: 5px; padding-right: 5px">
					<h3 id="__pl_upnext_text" style="vertical-align: middle; margin: 0px auto"></h3>
					<p id="__pl_upnext_author_text" style="vertical-align: bottom; margin: 0px; font-size: small"></p>
				</div>
			</div>
			<div class="_playlist_sub_bar">
				<p class="_playlist_sub_bar_el" style="margin-top: 5px; margin-bottom: 5px"><a id="__pl_goto_el" href="#">Go to playlist.</a></p>
				<span class="_playlist_sub_bar_el">&centerdot;</span>
				<div class="_playlist_sub_bar_el" id="__pl_index_div" style="display: none; visibility: hidden; margin-bottom: -5px">
					<!-- font-family: monospace; -->
					<p style="font-size: medium; margin-top: 5px; margin-bottom: 10px">This is track <span id="__pl_index">0</span> in the playlist.</p>
				</div>
			</div>
			<div style="clear: both"></div>
			<!--<div style="padding-bottom: 15px;"></div>-->
		</div>
		<div id="__endscreen" class="poly-item" style="display: none; visibility: hidden">
			<h3 style="margin-top: 5px; margin-bottom: 5px">Endscreen.</h3>
			<center>
				<style>
					.endscreen-video-idiv {
						display: table-cell;
						margin: auto 0px;
					}

					.endscreen-video {
						width: calc(50% - 5px);
						display: inline-flex !important;
						flex: 1;
						flex-basis: calc(50% - 5px);
					}

					.endscreen-video-poly {
						padding-left: 0px !important;
						margin-right: 2px;
						padding-bottom: 2px;
						margin-bottom: 2px !important;
					}

					.endscreen-link-main {
						color: inherit;
						text-decoration: none;
						margin-bottom: -2px;
					}

					#endscreen_div {
						-moz-flex-wrap: wrap;
						-webkit-flex-wrap: wrap;
						-webkit-box-flex-wrap: wrap;
						-ms-flex-wrap: wrap;
						flex-wrap: wrap;
						-moz-flex-direction: row;
						-webkit-flex-direction: row;
						-webkit-box-flex-direction: row;
						-ms-flex-direction: row;
						flex-direction: row;
					}

					@media only screen and (max-width: 600px) {
						.endscreen-video {
							flex-basis: 100vw !important;
						}
					}
				</style>
				<!--style="width: 100%;padding-bottom: 0px; display: flex; text-align: center; overflow-x: hidden;"-->
				<div id="endscreen_div" class="flex_box_compat flex_wrap_compat flex_direction_row_compat" style="width: 100%; padding-bottom: 0px; text-align: left">
					<!--<div class="poly-item endscreen-div-core">
						<a href="" style="color: inherit; text-decoration: none;">
							<img class="endscreen-div-img" src="https://i.ytimg.com/v/fi9dfsd/mqdefault.jpg">
							<div style="display: inline-block; padding-left: 5px; padding-right: 5px;">
								<p style="font-weight: bold; font-size: large; vertical-align: top;">$NEW_RELATED_TITLE</p>
								<p style="font-size: small; vertical-align: bottom;">$CHANNEL_NAME &centerdot; $DURATION &centerdot; PLAYLIST</p>
							</div>
						</a>
					</div>-->
				</div>
			</center>
		</div>
		<div class="poly-item">
			<h3 style="margin-top: 5px; margin-bottom: 5px">Related.</h3>
			<center>
				<style>
					.related-video-idiv {
						display: table-cell;
						margin: auto 0px;
					}

					.related-video {
						width: calc(50% - 5px);
						display: inline-flex !important;
						flex-basis: calc(50% - 5px);
						flex-grow: 1;
					}

					.related-video-poly {
						padding-left: 0px !important;
						margin-right: 2px;
						padding-bottom: 2px;
						margin-bottom: 2px !important;
					}

					.related-link-main {
						color: inherit;
						text-decoration: none;
						margin-bottom: -2px;
					}

					@media only screen and (max-width: 600px) {
						.related-div-core {
							flex-basis: 100vw !important;
						}

						.related-video {
							flex-basis: 100vw !important;
						}

						.related-text-main {
							width: 88vw !important;
						}
					}
				</style>
				<div id="related_div" class="flex_box_compat flex_wrap_compat flex_direction_row_compat" style="width: 100%; padding-bottom: 0px; text-align: left">
					<!--<div class="poly-item related-div-core">
						<a href="" style="color: inherit; text-decoration: none;">
							<img class="related-div-img" src="https://i.ytimg.com/v/fi9dfsd/mqdefault.jpg">
							<div style="display: inline-block; padding-left: 5px; padding-right: 5px;">
								<p style="font-weight: bold; font-size: large; vertical-align: top;">$NEW_RELATED_TITLE</p>
								<p style="font-size: small; vertical-align: bottom;">$CHANNEL_NAME &centerdot; $DURATION</p>
							</div>
						</a>
					</div>-->
				</div>
			</center>
			<p id="filtered_related_text" style="display: none; visibility: hidden; font-family: monospace; font-size: medium; margin-bottom: 5px; margin-top: 2px; text-align: center">
				nTube has hidden <span id="filtered_related_count">%NUMBER_COUNT</span> <span id="filtered_videos_text">videos</span>, in accordance to your filters.
			</p>
		</div>
		<div class="poly-item" style="overflow-x: hidden">
			<h3 style="margin-top: 5px; margin-bottom: 10px">Comments.</h3>
			<div id="_comments_initial_div" style="display: none; visibility: hidden">
				<button id="_comments_initial_button" class="flat-button" style="background-color: inherit; color: inherit; font-family: inherit; font-size: medium">Load comments.</button>
			</div>
			<div id="_sample_comments" style="display: none; visibility: hidden">
				<p style="font-family: monospace; font-size: medium">Displaying <span>0</span> comments.</p>
				<div class="poly-item" style="margin-right: 5px">
					<img decoding="async" src="" alt="profile pic." style="width: 48px; height: 48px; display: inline-table; vertical-align: middle" />
					<div style="display: inline-table; vertical-align: middle; margin-bottom: -6px">
						<p style="line-height: 5%"><span>Author.name</span>&nbsp;&centerdot;&nbsp;<span style="font-family: monospace">0 likes.</span>&nbsp;&centerdot;&nbsp;<span style="font-family: monospace">1 second ago.</span></p>
						<p style="line-height: 95%">Author.message<br />Author.message.line2</p>
					</div>
					<div style="clear: both; height: 0px"></div>
					<button style="background: inherit; border: 1px solid white; margin-bottom: 1px; margin-top: -5px">Load more.</button>
				</div>
			</div>
			<div>
				<p style="font-family: monospace; font-size: medium">Displaying <span id="_comments_count">0</span> <span id="_comments_tag">comments</span>.</p>
				<div id="_comments" class="poly-item" style="display: grid; margin-right: 5px; padding-left: 0px"></div>
			</div>
		</div>
		<style id="ntube-custom-css"></style>
		<script type="text/javascript" defer="defer">
			var coll = document.getElementsByClassName("collapsible");
			var i;

			for (i = 0; i < coll.length; i++) {
				coll[i].addEventListener("click", function () {
					this.classList.toggle("active");
					var content = this.nextElementSibling;
					var possHeight = content.attributes.getNamedItem("maxHeight");
					if (content.style.maxHeight) {
						content.style.maxHeight = null;
					} else if (possHeight != null) {
						if (possHeight.value === "force") {
							content.style.maxHeight = "max-content";
						} else {
							content.style.maxHeight = possHeight.value;
						}
					} else {
						content.style.maxHeight = content.scrollHeight + "px";
					}
				});
			}
		</script>
	</body>
</html>
